Je sais que la chaîne de mise en page automatique consiste essentiellement en 3 processus différents.
- mise à jour des contraintes
- vues de mise en page (c'est ici que nous obtenons le calcul des images)
- afficher
Ce qui n'est pas totalement clair pour moi, c'est la différence intérieure entre -setNeedsLayout
et -setNeedsUpdateConstraints
. Depuis Apple Docs:
Appelez cette méthode sur le thread principal de votre application lorsque vous souhaitez ajuster la disposition des sous-vues d'une vue. Cette méthode prend note de la demande et revient immédiatement. Étant donné que cette méthode ne force pas une mise à jour immédiate, mais attend le cycle de mise à jour suivant, vous pouvez l'utiliser pour invalider la disposition de plusieurs vues avant la mise à jour de l'une de ces vues. Ce comportement vous permet de consolider toutes vos mises à jour de mise en page en un seul cycle de mise à jour, ce qui est généralement meilleur pour les performances.
Lorsqu'une propriété de votre vue personnalisée change d'une manière qui aurait un impact sur les contraintes, vous pouvez appeler cette méthode pour indiquer que les contraintes doivent être mises à jour à un moment donné dans le futur. Le système appellera ensuite updateConstraints dans le cadre de sa passe de mise en page normale. La mise à jour simultanée des contraintes juste avant qu'elles ne soient nécessaires garantit que vous ne recalculez pas inutilement les contraintes lorsque plusieurs modifications sont apportées à votre vue entre les étapes de mise en page.
Lorsque je veux animer une vue après avoir modifié une contrainte et animer les changements que j'appelle habituellement par exemple:
[UIView animateWithDuration:1.0f delay:0.0f usingSpringWithDamping:0.5f initialSpringVelocity:1 options:UIViewAnimationOptionCurveEaseInOut animations:^{
[self.modifConstrView setNeedsUpdateConstraints];
[self.modifConstrView layoutIfNeeded];
} completion:NULL];
J'ai découvert que si j'utilise à la -setNeedsLayout
place de -setNeedsUpdateConstraints
tout fonctionne comme prévu, mais si je change -layoutIfNeeded
avec -updateConstraintsIfNeeded
, l'animation ne se produira pas.
J'ai essayé de tirer ma propre conclusion:
-updateConstraintsIfNeeded
ne met à jour que les contraintes mais ne force pas la mise en page à entrer dans le processus, donc les cadres d'origine sont toujours préservés-setNeedsLayout
appelle également la-updateContraints
méthode
Alors, quand est-il possible d'utiliser l'un au lieu de l'autre? et sur les méthodes de disposition, dois-je les appeler sur la vue qui a changé dans une contrainte ou sur la vue parent?
Réponses:
Vos conclusions sont justes. Le schéma de base est le suivant:
setNeedsUpdateConstraints
assure un futur appel auxupdateConstraintsIfNeeded
appelsupdateConstraints
.setNeedsLayout
assure un futur appel auxlayoutIfNeeded
appelslayoutSubviews
.Quand
layoutSubviews
est appelé, il appelle égalementupdateConstraintsIfNeeded
, donc l'appeler manuellement est rarement nécessaire dans mon expérience. En fait, je ne l'ai jamais appelé sauf lors du débogage de mises en page.La mise à jour des contraintes à l'aide
setNeedsUpdateConstraints
est également assez rare, objc.io - une lecture incontournable des mises en page automatiques - dit :De plus, d'après mon expérience, je n'ai jamais eu à invalider les contraintes et à ne pas définir la
setNeedsLayout
dans la ligne suivante du code, car les nouvelles contraintes demandent à peu près une nouvelle mise en page.Les règles de base sont les suivantes:
setNeedsLayout
.updateConstraints
méthode (une méthode recommandée aux contraintes de changement, BTW), appelsetNeedsUpdateConstraints
, et la plupart du temps,setNeedsLayout
après cela.layoutIfNeeded
.De plus, dans votre code d'animation, je pense que cela
setNeedsUpdateConstraints
n'est pas nécessaire, car les contraintes sont mises à jour manuellement avant l'animation, et l'animation ne fait que redisposer la vue en fonction des différences entre les anciennes et les nouvelles.la source
setNeedsLayout
.setNeedsLayout
s'assure quelayoutSubviews
sera appelé dans le prochain cycle de mise à jour, mais cela n'a peut-être rien à voir avec celalayoutIfNeeded
?layoutSubviews
sera appelé automatiquement, pas besoin d'appelersetNeedsLayout
layoutSubviews
, donc pas besoin de le faire manuellement. Vous devez cependant appelerlayoutIfNeeded
si vous avez besoin que les modifications prennent effet immédiatement au lieu du prochain cycle de mise en pageLa réponse par coverback est assez correcte. Cependant, je voudrais ajouter quelques détails supplémentaires.
Voici le schéma d'un cycle UIView typique qui explique d'autres comportements:
-setNeedsLayout
place de-setNeedsUpdateConstraints
tout fonctionne comme prévu, mais si je change-layoutIfNeeded
avec-updateConstraintsIfNeeded
, l'animation ne se produira pas.updateConstraints
ne fait généralement rien. Il résout simplement les contraintes, il ne les applique pas jusqu'à ce qu'illayoutSubviews
soit appelé. L'animation nécessite donc un appel àlayoutSubviews
.Non, ce n'est pas nécessaire. Si vos contraintes n'ont pas été modifiées, UIView ignorera l'appel à
updateConstraints
. Vous devez appeler explicitementsetNeedsUpdateConstraint
pour modifier les contraintes dans le processus.Pour appeler,
updateConstraints
vous devez procéder comme suit:la source