Après avoir fait une mise en page visuelle dans Interface Builder, j'ai créé quelques contraintes auxquelles je veux accéder au moment de l'exécution. Existe-t-il un moyen d'étiqueter ou d'identifier les contraintes dans Interface Builder afin qu'elles puissent être consultées plus tard?
La raison pour laquelle je veux le faire est que je dois effectuer une base de calcul sur les contraintes qui sont spécifiées visuellement. Je suis conscient que Apple a fourni le Visual Format Language et je pourrais spécifier les contraintes par programme dans un contrôleur. Je préfère ne pas utiliser cette approche pour ne pas perdre la rétroaction du temps de conception d'IB.
Faire un point de référence a bien fonctionné, mais la question demeure.
Mise à jour:
Comme expliqué par Bartłomiej Semańczyk dans sa réponse , il y a maintenant un champ Identifiant visible dans le Inspector Attributes pour le NSLayoutConstraint
rendant inutile d'exposer vous-même ce champ. Sélectionnez simplement la contrainte dans la vue Document Outline ou dans la vue Storyboard, puis ajoutez un identifiant dans la Inspector Attributes à droite.
Réponse antérieure:
Oui, cela peut être fait. NSLayoutConstraint
possède une propriété appelée identifier
qui peut être exposée dans Interface Builder et attribuée. Pour faire une démonstration, j'ai créé un Application à vue unique qui a une seule sous-vue qui est une boîte rouge. Cette sous-vue a 4 contraintes: largeur, hauteur, centrée horizontalement dans le conteneur, centrée verticalement dans le conteneur. J'ai donné à la contrainte de largeur l'identifiant redBoxWidth
en procédant comme suit:
Cliquez sur la contrainte de largeur dans la vue Mise en page du document. Ensuite, dans Identity Inspector sous Attributs d'exécution définis par l'utilisateur , cliquez sur +
sous Chemin de clé . Changer keyPath en identificateur, changer le Type Boolean à String, et définissez la valeur sur redBoxWidth
.
Puis dans ViewDidLoad
il est possible de trouver la contrainte par son nom et de changer sa valeur:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
for subview in view.subviews as [UIView] {
for constraint in subview.constraints() as [NSLayoutConstraint] {
if constraint.identifier == "redBoxWidth" {
constraint.constant = 300
}
}
}
}
}
Cependant, si vous configurez votre contrainte dans le code, procédez comme suit:
let constraint = NSLayoutConstraint()
constraint.identifier = "identifier"
Pour ces contraintes, vous avez configuré dans le storyboard, mais vous devez définir l'identifiant dans le code:
for subview in view.subviews {
for constraint in subview.constraints() {
constraint.identifier = "identifier"
}
}
Vous pouvez également lier la contrainte aux propriétés de votre contrôleur comme vous le faites pour tout autre composant. Faites-le simplement glisser et faites-le glisser dans votre code:
Et puis il sera accessible dans le code de votre contrôleur comme propriété:
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *myConstraint;
Et vous pouvez changer sa valeur par exemple:
self.myConstraint.constant=100.;
Ajout juste à la réponse de @ vacawama. Vous pouvez écrire une catégorie UIView
et extraire des contraintes à l'aide d'une fonction simple, par opposition aux boucles copier/coller partout où vous avez besoin de trouver une contrainte:
Fichier .h:
#import <UIKit/UIKit.h>
@interface UIView (EasyAutolayout)
-(NSLayoutConstraint *)constraintForIdentifier:(NSString *)identifier;
@end
Fichier .m:
#import "UIView+EasyAutolayout.h"
@implementation UIView (EasyAutolayout)
-(NSLayoutConstraint *)constraintForIdentifier:(NSString *)identifier {
for (NSLayoutConstraint *constraint in self.constraints) {
if ([constraint.identifier isEqualToString:identifier]) {
return constraint;
}
}
return nil;
}
@end
Prenez l'IBOutlet de votre contrainte de disposition automatique.
Il existe une propriété appelée constante dans la classe NSLayoutConstraint.
Par exemple, vous avez pris la contrainte IBOutlet de hauteur de l'une des vues de votre IB, et vous souhaitez modifier sa hauteur par programme, tout ce que vous devez faire est:
constraint.constant = isMoreHeight ? height1 : height2;
Après cela, vous devez mettre à jour toutes les autres vues dans la hiérarchie des vues de la vue d'ensemble. Pour ce faire, vous devrez écrire la ligne ci-dessous:
[self setLayoutIfNeeded];
Pour une meilleure expérience utilisateur, vous pouvez mettre cette ligne dans votre bloc d'animations pour des effets de transition plus fluides,
[UIView animateWithDuration:0.3f animations:^{
[self.view layoutIfNeeded];
}];
J'espère que cela t'aides..
Et ça:
if let myconstraint = self.view.constraints.filter( { $0.identifier == "myconstraintId" }).first {
// TODO: your code here...
}
mes deux cents pour OSX (les réponses précédentes concernent UIKit ..)
cela fonctionne aussi pour OSX:
final private func getConstraintForButton(){
let constraints = self.myButton.constraints
for constraint in constraints {
if constraint.identifier == "redBoxWidth" {
constraint.constant = 300
break
}
}
}
Remarque: semble ne pas fonctionner sur NSView personnalisé, à la place ...