Quand puis-je activer/désactiver les contraintes de mise en forme?
J'ai mis en place plusieurs ensembles de contraintes de l'IB, et j'aimerais par programme basculer entre eux en fonction de l'état. Il y a un constraintsA
sortie de la collection qui sont toutes marquées comme étant installé à partir de l'IB, et un constraintsB
sortie de la collection qui sont tous des désinstallé de l'IB.
Je peux par programme de basculer entre les deux ensembles comme:
NSLayoutConstraint.deactivateConstraints(constraintsA)
NSLayoutConstraint.activateConstraints(constraintsB)
Mais... je ne peux pas comprendre quand de le faire. Il semble que je devrais être capable de le faire une fois dans viewDidLoad
, mais je ne peux pas obtenir que cela fonctionne. J'ai essayé d'appeler view.updateConstraints()
et view.layoutSubviews()
après la mise à l'contraintes, mais en vain.
Je l'ai fait savoir que si j'ai mis les contraintes dans viewDidLayoutSubviews
tout fonctionne comme prévu. Je suppose que je voudrais savoir deux choses...
- Pourquoi suis-je ce problème?
- Est-il possible d'activer/désactiver les contraintes de viewDidLoad?
- Entendez-vous le deactivateConstraints et activateConstraints travaillé dans viewWillLayoutSubviews? J'ai essayé, et ça n'a pas de travail là-bas ou dans viewDidLoad. Il a travaillé dans viewDidAppear; le point de vue est apparu où les nouvelles contraintes doit le mettre, mais si j'ai tourné vers le paysage, la vue est déplacé à la position déterminée par les contraintes de l'IB (et y est resté quand j'ai tourné le dos à portrait). L'enregistrement de l'contraintes, a montré les bons (ceux nouvellement activé). Cela semble être un bug pour moi.
- oui il a travaillé pour moi dans viewWillLayoutSubviews. Peut-être les contraintes que vous avez essayé d'activer n'étaient pas valides? Ou peut-être oublié d'appeler super?
- Oui, ils étaient valides (ils ont travaillé dans viewDidAppear), et il n'y a pas besoin d'appeler super car il n'y a pas de défaut de mise en œuvre de viewWillLayoutSubviews (je l'ai essayé avec un appel à super de toute façon, mais qui ne fait pas de différence).
- De toute façon, je ne sais pas pourquoi cela ne fonctionnerait pas dans le viewDidLoad. J'ai ajouté des contraintes dans le passé, et qui fonctionne très bien.
- Bizarre. J'espère qu'il y est une bonne réponse. J'aimerais mieux comprendre ce processus.
- J'ai essayé une autre chose à vérifier qu'elle n'a pas un problème de synchronisation. J'ai appelé ces deux méthodes dans un timer de la méthode d'action qui a été appelé 2 secondes après viewDidLoad. J'ai obtenu les mêmes résultats que j'ai obtenu avec viewDidAppear -- le point de vue a été dans sa nouvelle position, mais est revenue sur la rotation.
- Juste eu la chance d'aller tester plus... je peux vérifier j'ai effectivement eu le même comportement que vous avez décrit... travaille d'abord dans viewDidAppear, mais il reprend ensuite lors de la rotation.
- Je me demande si, lorsque vous avez eu le succès ajout de contraintes de viewDidLoad si vous n'étiez pas à l'aide adaptative points de vue, mais maintenant vous êtes?
- Apparemment, vous ne pouvez pas marquer les contraintes qu'il n'est pas installé dans l'IB à cette fin. Constaté que les renseignements ici: stackoverflow.com/questions/27663249/... et il a résolu le problème pour moi.
- J'ai eu mes contraintes de mise en œuvre de la même manière que celle décrite dans la question, sauf que j'ai activé/désactivé certains d'entre eux dans viewDidAppear. Cela a fonctionné, mais vous pouvez voir les éléments de changer rapidement de position (un mineur, mais indésirable de l'émission). Le changement dans viewWillAppear ou viewDidLoad n'a pas de travail. Mais après la lecture de cette question, j'ai essayé de faire ce changement dans viewDidLayoutSubviews. Cela a fonctionné, et le changement de position n'est plus visible pour l'utilisateur. (Il a également travaillé dans viewWillLayoutSubviews). Donc merci pour cette astuce!
- Pour moi le seul moyen fiable est d'ajuster les contraintes dans
viewDidLayoutSubviews()
. Réglage de contraintes dansviewWillLayoutSubviews()
ne fonctionne pas dans mon cas.
Vous devez vous connecter pour publier un commentaire.
Je activer et de désactiver
NSLayoutConstraints
dansviewDidLoad
, et je n'ai pas de problèmes avec elle. Donc, il ne le travail. Il doit y avoir une différence de configuration entre votre application et le mien 🙂Je vais décrire mon installation - peut-être que cela peut vous donner un plomb:
@IBOutlets
pour toutes les contraintes que j'ai besoin d'activer/désactiver.ViewController
, je sauvegarde les contraintes dans la classe des propriétés qui ne sont pas faibles. La raison pour cela est que j'ai trouvé qu'après la désactivation d'une contrainte, je ne pouvais pas réactiver, c'est nul. Ainsi, il semble être supprimés quand il est désactivé.NSLayoutConstraint.deactivate/activate
comme vous le faites, j'utiliseconstraint.active = YES
/NO
à la place.view.layoutIfNeeded()
..active = false
attend qu'ils seraient ignorés jusqu'à ce que je les mettre à l'actif.Peut-être vous pourriez vérifier votre
@properties
, remplacerweak
avecstrong
.Parfois parce que
active = NO
ensembleself.yourConstraint = nil
, de sorte que vous ne pouvez pas utiliserself.yourConstraint
de nouveau.weak
et qui va le faire.Je crois que le problème que vous rencontrez est en raison de contraintes de ne pas être ajoutée à leur point de vue jusqu'à ce que APRÈS
viewDidLoad()
est appelé. Vous avez un certain nombre d'options:A) vous pouvez Vous connecter à votre disposition des contraintes à un IBOutlet et l'accès dans votre code par ces références. Depuis les sorties sont connectées avant de
viewDidLoad()
coup d'envoi, les contraintes doivent être accessibles et vous pouvez continuer à les activer et les désactiver il.B) Si vous souhaitez utiliser UIView de
constraints()
fonction pour accéder aux différentes contraintes que vous devez attendre pourviewDidLayoutSubviews()
le coup d'envoi, et de le faire là, puisque c'est le premier point après la création d'une vue contrôleur à partir d'une plume qu'il va avoir tout installé des contraintes. N'oubliez pas d'appelerlayoutIfNeeded()
lorsque vous avez terminé. Cela a l'inconvénient que le schéma de passage sera effectué en deux fois si il y a des changements à appliquer et vous devez vous assurer qu'il n'y a pas de possibilité qu'une boucle infinie sera déclenchée.Un petit mot d'avertissement: désactivé les contraintes ne sont PAS retournés par la
constraints()
méthode! Cela signifie que si vous désactivez une contrainte avec l'intention de le rallumer de nouveau plus tard, vous aurez besoin de garder une référence.C) Vous pouvez oublier sur la table de montage séquentiel approche et ajouter vos contraintes manuellement à la place. Depuis que vous faites cela dans
viewDidLoad()
je suppose que l'intention est de ne le faire qu'une fois pour la durée de vie totale de l'objet plutôt que de changer la mise en page à la volée, donc cela devrait être une méthode acceptable.Vous pouvez également régler la
priority
à la propriété "activer" et "désactiver" les (750 valeur pour activer et de 250 à désactiver par exemple). Pour une raison quelconque modification de laactive
BOOL n'a pas eu d'effet sur mon INTERFACE. Pas besoin delayoutIfNeeded
et peuvent être définies et modifiées à viewDidLoad ou à tout autre moment par la suite.viewWillTransition(to:, with:)
ouviewWillLayoutSubviews()
et vous pouvez garder tous vos alternative contraintes comme "installé" dans un storyboard. Contrainte de priorité ne peut pas changer de non-requis nécessaires, afin d'utiliser les valeurs ci-dessous1000
. D'autre part, l'activation (ajout) et de désactiver (supprimer) les contraintes ne fonctionne que dansviewDidLayoutSubviews()
et nécessite de garderstrong
@IBOutlet
références àNSLayoutConstraint
-s.Le bon moment pour désactiver inutilisés contraintes:
Gardez à l'esprit que
viewWillLayoutSubviews
pourrait être appelée plusieurs fois, donc pas de lourds calculs ici, ok?Remarque: si vous voulez réactif certaines des contraintes plus tard, puis rangez toujours
strong
référence.viewDidLayoutSubviews()
. Réglage de contraintes dansviewWillLayoutSubviews()
ne fonctionne pas dans mon cas.Lorsqu'une vue est créée les suivantes du cycle de vie méthodes sont appelées dans l'ordre:
Maintenant à vos questions.
Réponse: Parce que quand vous essayez de définir des contraintes sur les points de vue dans
viewDidLoad
le point de vue n'a pas ses limites, d'où les contraintes ne peuvent pas être définies. C'est seulement aprèsviewDidLayoutSubviews
que le point de vue de l'limites sont finalisés.Réponse: Non. Raison expliquée ci-dessus.
J'ai trouvé aussi longtemps que vous définissez les contraintes normale dans la substitution de
- (void)updateConstraints
(objective-c), avec unstrong
de référence pour la initiality utilisé active et de l'onu-des contraintes actives. Et d'ailleurs, dans le point de vue du cycle de désactiver et/ou d'activer ce dont vous avez besoin, puis de l'appel d'layoutIfNeeded
, vous devriez avoir aucun problème.La chose principale est de ne pas constamment réutiliser le remplacement de
updateConstraints
et de séparer les activations des contraintes, aussi longtemps que vous appelezupdateConstraint
s après votre première initialisation et la mise en page. Il ne semble pas à la matière après que, si le point de vue du cycle.