J'ai mis en place plusieurs ensembles de contraintes dans IB et j'aimerais basculer entre eux par programmation en fonction d'un état. Il y a une constraintsA
collection de points de vente qui sont tous marqués comme installés à partir d'IB et une constraintsB
collection de points de vente qui sont tous désinstallés dans IB.
Je peux basculer par programmation entre les deux ensembles comme ceci:
NSLayoutConstraint.deactivateConstraints(constraintsA)
NSLayoutConstraint.activateConstraints(constraintsB)
Mais ... je ne sais pas quand faire ça. Il semble que je devrais pouvoir le faire une fois viewDidLoad
, mais je ne peux pas le faire fonctionner. J'ai essayé d'appeler view.updateConstraints()
et view.layoutSubviews()
après avoir défini les contraintes, mais en vain.
J'ai trouvé que si je définissais les contraintes dans viewDidLayoutSubviews
tout fonctionne comme prévu. Je suppose que j'aimerais savoir deux choses ...
- Pourquoi ai-je ce comportement?
- Est-il possible d'activer / désactiver les contraintes de viewDidLoad?
la source
Réponses:
J'active et je désactive
NSLayoutConstraints
dansviewDidLoad
, et je n'ai aucun problème avec cela. Donc ça marche. Il doit y avoir une différence de configuration entre votre application et la mienne :-)Je vais juste décrire ma configuration - peut-être que cela peut vous donner une piste:
@IBOutlets
toutes les contraintes dont j'ai besoin pour activer / désactiver.ViewController
, j'enregistre les contraintes dans des propriétés de classe qui ne sont pas faibles. La raison en est que j'ai constaté qu'après avoir désactivé une contrainte, je ne pouvais pas la réactiver - c'était nul. Ainsi, il semble être supprimé lorsqu'il est désactivé.NSLayoutConstraint.deactivate/activate
comme vous, j'utiliseconstraint.active = YES
/ à laNO
place.view.layoutIfNeeded()
.la source
.active = false
m'attendant à ce qu'elles soient ignorées jusqu'à ce que je les définisse sur actives.Peut-être que vous pourriez vérifier votre
@properties
, remplacerweak
parstrong
.Parfois, c'est parce que
active = NO
définiself.yourConstraint = nil
, de sorte que vous ne pouvez plus utiliserself.yourConstraint
.la source
weak
et cela le fera.la source
Je pense que le problème que vous rencontrez est dû au fait que des contraintes ne sont ajoutées à leurs opinions qu'APRÈS
viewDidLoad()
appel d’ . Vous avez plusieurs options:UNE) Vous pouvez connecter vos contraintes de mise en page à un IBOutlet et y accéder dans votre code par ces références. Les prises étant connectées avant le
viewDidLoad()
coup d'envoi, les contraintes doivent être accessibles et vous pouvez continuer à les activer et à les désactiver à cet endroit.B) Si vous souhaitez utiliser la
constraints()
fonction d' UIView pour accéder aux différentes contraintes, vous devez attendre pour démarrerviewDidLayoutSubviews()
et le faire là-bas, car c'est le premier point après la création d'un contrôleur de vue à partir d'une pointe où il aura toutes les contraintes installées. N'oubliez pas d'appelerlayoutIfNeeded()
lorsque vous avez terminé. Cela présente l'inconvénient que la passe de mise en page sera effectuée deux fois s'il y a des changements à appliquer et vous devez vous assurer qu'il n'y a aucune possibilité qu'une boucle infinie soit déclenchée.Un petit mot d'avertissement: les contraintes désactivées ne sont PAS renvoyées par la
constraints()
méthode! Cela signifie que si vous désactivez une contrainte avec l'intention de la réactiver plus tard, vous devrez en garder une référence.C) Vous pouvez oublier l'approche du storyboard et ajouter vos contraintes manuellement à la place. Puisque vous faites cela dans,
viewDidLoad()
je suppose que l'intention est de ne le faire qu'une seule fois pendant toute la durée de vie de l'objet plutôt que de changer la mise en page à la volée, donc cela devrait être une méthode acceptable.la source
Vous pouvez également ajuster la
priority
propriété pour les «activer» et les «désactiver» (valeur 750 pour activer et 250 pour désactiver par exemple). Pour une raison quelconque, la modification deactive
BOOL n'a eu aucun effet sur mon interface utilisateur. Pas besoinlayoutIfNeeded
et peut être défini et modifié à viewDidLoad ou à tout moment par la suite.la source
viewWillTransition(to:, with:)
ouviewWillLayoutSubviews()
et vous pouvez conserver toutes vos contraintes alternatives comme «installées» dans un storyboard. La priorité de contrainte ne peut pas changer de non obligatoire à obligatoire, utilisez donc les valeurs ci-dessous1000
. D'autre part, l'activation (l'ajout) et la désactivation (la suppression) des contraintes ne fonctionnent que dansviewDidLayoutSubviews()
et nécessitent de conserver lesstrong
@IBOutlet
références àNSLayoutConstraint
-s.Le bon moment pour désactiver les contraintes inutilisées:
Gardez à l'esprit que cela
viewWillLayoutSubviews
pourrait être appelé plusieurs fois, donc pas de calculs lourds ici, d'accord?Remarque: si vous souhaitez réactiver certaines des contraintes ultérieurement, enregistrez toujours la
strong
référence à celles-ci.la source
viewDidLayoutSubviews()
. L'ajustement des contraintes dansviewWillLayoutSubviews()
ne fonctionne pas dans mon cas.Lorsqu'une vue est créée, les méthodes de cycle de vie suivantes sont appelées dans l'ordre:
Passons maintenant à vos questions.
Réponse: Parce que lorsque vous essayez de définir les contraintes sur les vues dans
viewDidLoad
la vue n'a pas ses limites, par conséquent les contraintes ne peuvent pas être définies. Ce n'est qu'aprèsviewDidLayoutSubviews
que les limites de la vue sont finalisées.Réponse: Non. Raison expliquée ci-dessus.
la source
J'ai trouvé tant que vous avez mis en place les contraintes par normale dans le remplacement de
- (void)updateConstraints
(objectif c), avec unestrong
référence pour l'initialité utilisée des contraintes actives et inactives. Et ailleurs dans le cycle de visualisation, désactivez et / ou activez ce dont vous avez besoin, puis appelezlayoutIfNeeded
, vous ne devriez avoir aucun problème.L'essentiel est de ne pas réutiliser constamment le remplacement
updateConstraints
et de séparer les activations des contraintes, tant que vous appelezupdateConstraint
s après votre première initialisation et mise en page. Il semble important après cela, où dans le cycle de visualisation.la source