Ich weiß, dass die Auto-Layout-Kette im Grunde genommen aus 3 verschiedenen Prozessen besteht.
- Einschränkungen aktualisieren
- Layoutansichten (hier erhalten wir die Berechnung von Frames)
- Anzeige
Was mir nicht ganz klar ist, ist der innere Unterschied zwischen -setNeedsLayout
und -setNeedsUpdateConstraints
. Aus Apple Docs:
Rufen Sie diese Methode im Hauptthread Ihrer Anwendung auf, wenn Sie das Layout der Unteransichten einer Ansicht anpassen möchten. Diese Methode notiert die Anfrage und kehrt sofort zurück. Da diese Methode keine sofortige Aktualisierung erzwingt, sondern auf den nächsten Aktualisierungszyklus wartet, können Sie damit das Layout mehrerer Ansichten ungültig machen, bevor eine dieser Ansichten aktualisiert wird. Mit diesem Verhalten können Sie alle Layout-Updates in einem Update-Zyklus konsolidieren, was normalerweise die Leistung verbessert.
Wenn sich eine Eigenschaft Ihrer benutzerdefinierten Ansicht so ändert, dass sie sich auf Einschränkungen auswirkt, können Sie diese Methode aufrufen, um anzugeben, dass die Einschränkungen zu einem späteren Zeitpunkt aktualisiert werden müssen. Das System ruft dann updateConstraints als Teil seines normalen Layoutdurchlaufs auf. Durch das gleichzeitige Aktualisieren von Einschränkungen, bevor sie benötigt werden, wird sichergestellt, dass Sie Einschränkungen nicht unnötig neu berechnen, wenn zwischen den Layoutdurchläufen mehrere Änderungen an Ihrer Ansicht vorgenommen werden.
Wenn ich eine Ansicht nach dem Ändern einer Einschränkung animieren und die Änderungen animieren möchte, die ich normalerweise aufrufe, zum Beispiel:
[UIView animateWithDuration:1.0f delay:0.0f usingSpringWithDamping:0.5f initialSpringVelocity:1 options:UIViewAnimationOptionCurveEaseInOut animations:^{
[self.modifConstrView setNeedsUpdateConstraints];
[self.modifConstrView layoutIfNeeded];
} completion:NULL];
Ich habe herausgefunden, dass , wenn ich -setNeedsLayout
statt -setNeedsUpdateConstraints
alles wie erwartet, aber wenn ich ändern -layoutIfNeeded
mit -updateConstraintsIfNeeded
, die Animation wird nicht passieren.
Ich habe versucht, meine eigene Schlussfolgerung zu ziehen:
-updateConstraintsIfNeeded
aktualisiert nur Einschränkungen, erzwingt jedoch nicht, dass das Layout in den Prozess einfließt, sodass die ursprünglichen Frames weiterhin erhalten bleiben-setNeedsLayout
ruft auch-updateContraints
Methode auf
Wann ist es also in Ordnung, eines anstelle des anderen zu verwenden? Muss ich die Layoutmethoden in der Ansicht aufrufen, in der sich eine Einschränkung geändert hat, oder in der übergeordneten Ansicht?
Antworten:
Ihre Schlussfolgerungen sind richtig. Das Grundschema ist:
setNeedsUpdateConstraints
stellt sicher, dass ein zukünftiger AnrufupdateConstraintsIfNeeded
anruftupdateConstraints
.setNeedsLayout
stellt sicher, dass ein zukünftiger AnruflayoutIfNeeded
anruftlayoutSubviews
.Wenn
layoutSubviews
es aufgerufen wird, ruft es auch anupdateConstraintsIfNeeded
, so dass es meiner Erfahrung nach selten erforderlich ist, es manuell aufzurufen. Tatsächlich habe ich es nie aufgerufen, außer beim Debuggen von Layouts.Das Aktualisieren von Einschränkungen mithilfe von
setNeedsUpdateConstraints
ist ebenfalls ziemlich selten. Objc.io - ein Muss für Autolayouts - sagt :Außerdem musste ich meiner Erfahrung nach niemals Einschränkungen ungültig machen und die
setNeedsLayout
in der nächsten Zeile des Codes nicht festlegen , da neue Einschränkungen so ziemlich ein neues Layout erfordern.Die Faustregeln sind:
setNeedsLayout
.updateConstraints
Methode ändern würden (eine empfohlene Methode zum Ändern von Einschränkungen, übrigens), rufen Sie diesetNeedsUpdateConstraints
meiste ZeitsetNeedsLayout
danach auf.layoutIfNeeded
.Ich glaube auch, dass in Ihrem Animationscode dies
setNeedsUpdateConstraints
nicht erforderlich ist, da Einschränkungen vor der Animation manuell aktualisiert werden und die Animation die Ansicht nur basierend auf den Unterschieden zwischen den alten und neuen neu auslegt.quelle
setNeedsLayout
.setNeedsLayout
stellt sicherlayoutSubviews
, dass es im nächsten Aktualisierungszyklus aufgerufen wird, aber vielleicht hat dies nichts damit zu tunlayoutIfNeeded
?layoutSubviews
wird automatisch aufgerufen, keine Notwendigkeit zu rufensetNeedsLayout
layoutSubviews
wenn Sie die Eigenschaften einer Einschränkung direkt bearbeiten , wird dies ausgelöst , sodass Sie sie nicht manuell ausführen müssen. Sie müssen jedoch anrufen,layoutIfNeeded
wenn die Änderungen sofort wirksam werden sollen, anstatt des nächsten LayoutzyklusDie Antwort per Coverback ist ziemlich richtig. Ich möchte jedoch einige zusätzliche Details hinzufügen.
Unten sehen Sie das Diagramm eines typischen UIView-Zyklus, in dem andere Verhaltensweisen erläutert werden:
-setNeedsLayout
statt-setNeedsUpdateConstraints
alles wie erwartet, aber wenn ich ändern-layoutIfNeeded
mit-updateConstraintsIfNeeded
, die Animation wird nicht passieren.updateConstraints
macht normalerweise nichts. Es werden nur Einschränkungen aufgelöst, die erst angewendet werden, wenn sielayoutSubviews
aufgerufen werden. Für die Animation ist also ein Anruf bei erforderlichlayoutSubviews
.Nein, das ist nicht nötig. Wenn Ihre Einschränkungen nicht geändert wurden, überspringt UIView den Anruf zu
updateConstraints
. Sie müssen explizit aufrufensetNeedsUpdateConstraint
, um Einschränkungen im Prozess zu ändern.Um anzurufen
updateConstraints
, müssen Sie Folgendes tun:quelle