web-dev-qa-db-fra.com

Activer + désactiver les contraintes de disposition automatique

J'ai un problème simple (je pense): j'ai un UIImageView, pour lequel j'ai défini plusieurs contraintes dans le storyboard.

Parfois, je devrai désactiver les contraintes et définir son frame manuellement, mais plus tard, je voudrai réactiver ces contraintes et faire revenir la vue là où elle était comme décidé par les contraintes .

Je pensais pouvoir faire ça avec quelque chose comme:

@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var constraint: NSLayoutConstraint!

func example() { 

    //to set its location and size manually
    imageView.removeConstraint(constraint) 
    imageView.frame = CGRectMake(...)

    //to cause it to return to its original position
    imageView.addConstraint(constraint) 

}

Avec cela, cependant, j'obtiens l'erreur 2015-08-26 01:14:55.417 Constraints[18472:923024] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x7fbb72815f90 V:[_UILayoutGuide:0x7fbb72814c20]-(100)-[UIImageView:0x7fbb72814540]>. Quelqu'un sait-il pourquoi cette erreur se produit?

L'ajout à la place des contraintes à view en appelant self.view.addConstraint(...) supprime l'erreur, mais ne ramène toujours pas la vue d'image là où elle devrait être.

Je remarque que je n'ai même pas besoin de supprimer ou de désactiver les contraintes pour pouvoir définir le cadre du imageView sans problème, tant que je n'appelle pas setTranslatesAutoresizingMaskIntoConstraints(true).

J'ai déjà vu this question, mais la réponse semble inutilement compliquée, peut-être dépassée et même inapplicable.

J'ai aussi vu this question, mais cela ne couvre pas les contraintes qui peuvent être réactivées - seulement comment elles peuvent être désactivées.

Essayer de définir la propriété active:

self.top.active = false
self.right.active = false
self.bottom.active = false
self.left.active = false

imageView.frame = CGRectMake(100, 100, 100, 100)

Cela se traduit en fait juste par imageView n'est plus visible. (Si je ne mets pas la propriété active de toutes les contraintes à false, cependant, imageView se déplace à la bonne position.

Le vrai problème, cependant, est que lorsque j'essaie de faire revenir la vue de l'image à sa place, en définissant la propriété active de toutes les contraintes sur true, rien ne se passe - l'imageView reste où elle était (dans ce cas spécifié par imageView.frame = CGRectMake(100, 100, 100, 100).

En outre, il semble, selon mes tests et la réponse de Joachim Bøggild ici , que lorsque la propriété active d'une contrainte est définie sur false, cette contrainte devient nulle et ne peut donc pas être réactivée .

Ajout de contraintes à un tableau et activation/désactivation de celles-ci:

Fait intéressant, cela provoque presque exactement les mêmes problèmes que la définition de la propriété active. Placer toutes les contraintes dans un tableau array, puis appeler NSLayoutConstraint.deactivateConstraints(array) fait disparaître la vue de l'image. De plus, la réactivation ultérieure des contraintes avec NSLayoutConstraint.activateConstraints(array) ne fait pas revenir la vue d'image là où elle devrait - elle reste là où elle était.

31
Randoms

Aha!

Les contraintes deviennent nulles (et ne peuvent donc pas être réactivées), une fois que leur propriété active est définie sur false. Les faire références fortes (merci, Caleb, pour avoir clarifié la nomenclature) les conserve afin qu'ils puissent être activés et désactivés comme vous le souhaitez.

64
Randoms

Si vous consultez la documentation de NSLayoutConstraint, vous trouverez une section intitulée Activation et désactivation des contraintes qui décrit les active property , qui à son tour vous indique:

Vous pouvez activer ou désactiver une contrainte en modifiant cette propriété ... L'activation ou la désactivation de la contrainte appelle addConstraint: et removeConstraint: sur la vue qui est l'ancêtre commun le plus proche des éléments gérés par cette contrainte. Utilisez cette propriété au lieu d'appeler addConstraint: ou removeConstraint: directement.

Donc, une fois que vous avez une référence strong à la contrainte en question (comme celle que vous avez avec votre sortie), vous pouvez définissez simplement sa propriété active sur false (ou NO dans Obj-C) pour désactiver, ou true (ou YES) sur activer.

31
Caleb

Connectez Constraint en tant qu'IBOutlet du storyboard à ViewController et créez une contrainte Array add All dans le tableau.

Désactivez ces contraintes lorsqu'elles ne sont pas utilisées.

Ajoutez une contrainte à chaque utilisation.

NSLayoutConstraint *constraint1;
NSLayoutConstraint *constraint2;
NSLayoutConstraint *constraint3;
NSArray *arr = @[constraint1,constraint2,constraint3];
 [NSLayoutConstraint deactivateConstraints:arr];

//After deactivate constraint array add what ever frame you want to add

//Activate  lateroN
[NSLayoutConstraint activateConstraints:arr];
1
Kavita