Je sais que la chaîne de mise en page automatique consiste essentiellement en 3 processus différents.
Ce qui n’est pas tout à fait clair pour moi, c’est la différence intérieure entre -setNeedsLayout
et -setNeedsUpdateConstraints
. De Apple Docs:
Appelez cette méthode sur le thread principal de votre application lorsque vous souhaitez ajuster la présentation des sous-vues d’une vue. Cette méthode prend note de la demande et retourne immédiatement. Comme cette méthode ne force pas une mise à jour immédiate, mais attend le prochain cycle de mise à jour, vous pouvez l'utiliser pour invalider la mise en page de plusieurs vues avant la mise à jour de l'une de ces vues. Ce comportement vous permet de consolider toutes vos mises à jour de présentation en un 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 ultérieurement. Le système appelle ensuite updateConstraints dans le cadre de sa passe de présentation normale. La mise à jour simultanée des contraintes juste avant leur utilisation vous évite de recalculer inutilement les contraintes lorsque plusieurs modifications sont apportées à votre vue entre les étapes de présentation.
Lorsque je souhaite animer une vue après avoir modifié une contrainte et animer les modifications, j'appelle généralement 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 -setNeedsLayout
au lieu de -setNeedsUpdateConstraints
tout fonctionne comme prévu, mais si je change de -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, les images d'origine sont donc conservées-setNeedsLayout
appelle également la méthode -updateContraints
Alors, quand est-il possible d'utiliser l'un au lieu de l'autre? et à propos des méthodes de présentation, dois-je les appeler sur la vue modifiée dans une contrainte ou sur la vue parent?
Vos conclusions sont correctes. Le schéma de base est le suivant:
setNeedsUpdateConstraints
s'assure qu'un futur appel à updateConstraintsIfNeeded
appelle updateConstraints
.setNeedsLayout
s'assure qu'un futur appel à layoutIfNeeded
appelle layoutSubviews
.Lorsque layoutSubviews
est appelé, il appelle également updateConstraintsIfNeeded
. Il est donc rarement nécessaire de l'appeler manuellement, selon mon expérience. En fait, je ne l’ai jamais appelée, sauf lors du débogage de maquettes.
La mise à jour des contraintes à l'aide de setNeedsUpdateConstraints
est assez rare aussi, objc.io - une information à connaître sur les autolayouts - dit :
Si quelque chose change plus tard qui invalide l’une de vos contraintes, vous devez immédiatement la retirer et appeler setNeedsUpdateConstraints. En fait, c’est le seul cas où vous devriez avoir à déclencher un passage de mise à jour de contrainte.
De plus, d'après mon expérience, je n'ai jamais eu à invalider de contraintes ni à définir la setNeedsLayout
dans la ligne suivante du code, car les nouvelles contraintes demandent à peu près une nouvelle présentation.
Les règles de base sont les suivantes:
setNeedsLayout
.updateConstraints
remplacée (méthode recommandée pour modifier les contraintes, au fait), appelez setNeedsUpdateConstraints
et la plupart du temps, setNeedsLayout
après cela.layoutIfNeeded
.De plus, dans votre code d'animation, j'estime que setNeedsUpdateConstraints
n'est pas nécessaire, car les contraintes sont mises à jour manuellement avant l'animation, et l'animation ne fait que redistribuer la vue en fonction des différences entre l'ancienne et la nouvelle.
Le répondre par coverback est plutôt correct. Cependant, je voudrais ajouter quelques détails supplémentaires.
Vous trouverez ci-dessous le schéma d’un cycle typique d’UIView qui explique d’autres comportements:
-setNeedsLayout
au lieu de -setNeedsUpdateConstraints
tout fonctionne comme prévu, mais si je change de -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 que layoutSubviews
soit appelé. Donc, l'animation nécessite un appel à layoutSubviews
.
Non ce n'est pas nécessaire. Si vos contraintes n'ont pas été modifiées, UIView ignorera l'appel de updateConstraints
. Vous devez appeler explicitement setNeedsUpdateConstraint
pour modifier les contraintes dans le processus.
Pour appeler updateConstraints
, vous devez procéder comme suit:
[view setNeedsUpdateConstraints];
[view setNeedsLayout];
[view layoutIfNeeded];