Ich habe in IB mehrere Sätze von Einschränkungen eingerichtet und möchte je nach Status programmgesteuert zwischen diesen wechseln. Es gibt eine constraintsA
Outlet-Sammlung, die alle als von IB installiert markiert sind, und eine constraintsB
Outlet-Sammlung, die alle in IB deinstalliert sind.
Ich kann programmgesteuert zwischen den beiden Sätzen umschalten:
NSLayoutConstraint.deactivateConstraints(constraintsA)
NSLayoutConstraint.activateConstraints(constraintsB)
Aber ... ich kann nicht herausfinden, wann ich das tun soll. Es scheint, als sollte ich das einmal tun können viewDidLoad
, aber ich kann das nicht zum Laufen bringen. Ich habe versucht anzurufen view.updateConstraints()
und view.layoutSubviews()
nach dem Festlegen der Einschränkungen, aber ohne Erfolg.
Ich habe festgestellt, dass, wenn ich die Einschränkungen in viewDidLayoutSubviews
allem festlege, alles wie erwartet funktioniert. Ich würde gerne zwei Dinge wissen ...
- Warum bekomme ich dieses Verhalten?
- Ist es möglich, Einschränkungen in viewDidLoad zu aktivieren / deaktivieren?
quelle
Antworten:
Ich aktiviere und deaktiviere
NSLayoutConstraints
inviewDidLoad
und habe keine Probleme damit. Also funktioniert es. Es muss einen Unterschied im Setup zwischen deiner und meiner App geben :-)Ich beschreibe nur mein Setup - vielleicht kann es Ihnen einen Hinweis geben:
@IBOutlets
alle Einschränkungen eingerichtet, die ich zum Aktivieren / Deaktivieren benötige.ViewController
speichere ich die Einschränkungen in Klasseneigenschaften, die nicht schwach sind. Der Grund dafür ist, dass ich festgestellt habe, dass ich eine Einschränkung nach dem Deaktivieren nicht reaktivieren konnte - sie war gleich Null. Es scheint also gelöscht zu werden, wenn es deaktiviert ist.NSLayoutConstraint.deactivate/activate
wie du, ich benutzeconstraint.active = YES
/NO
stattdessen.view.layoutIfNeeded()
.quelle
.active = false
erwartet hatte, dass sie ignoriert werden, bis ich sie auf aktiv setze.Vielleicht könnten Sie Ihre überprüfen
@properties
, ersetzenweak
durchstrong
.Manchmal ist es so
active = NO
eingestelltself.yourConstraint = nil
, dass man es nicht mehr benutzen kannself.yourConstraint
.quelle
weak
können.quelle
Ich glaube, das Problem, auf das Sie stoßen, ist darauf zurückzuführen, dass Einschränkungen erst dann zu ihren Ansichten hinzugefügt werden, wenn AFTER
viewDidLoad()
aufgerufen wird. Sie haben eine Reihe von Optionen:A) Sie können Ihre Layouteinschränkungen mit einem IBOutlet verbinden und über diese Referenzen in Ihrem Code darauf zugreifen. Da die Steckdosen vor dem
viewDidLoad()
Start verbunden sind, sollten die Einschränkungen zugänglich sein und Sie können sie dort weiterhin aktivieren und deaktivieren.B) Wenn Sie die
constraints()
Funktion von UIView verwenden möchten, um auf die verschiedenen Einschränkungen zuzugreifen, müssen Sie warten, bis sie gestartet werdenviewDidLayoutSubviews()
, da dies der erste Punkt nach dem Erstellen eines Ansichtscontrollers aus einer Schreibfeder ist, auf dem alle Einschränkungen installiert sind. Vergessen Sie nicht anzurufen,layoutIfNeeded()
wenn Sie fertig sind. Dies hat den Nachteil, dass der Layoutdurchlauf zweimal ausgeführt wird, wenn Änderungen vorgenommen werden müssen, und Sie müssen sicherstellen, dass keine Möglichkeit besteht, dass eine Endlosschleife ausgelöst wird.Ein kurzes Wort zur Warnung: Deaktivierte Einschränkungen werden von der Methode NICHT zurückgegeben
constraints()
! Wenn Sie also eine Einschränkung deaktivieren, um sie später wieder einzuschalten, müssen Sie einen Verweis darauf behalten.C) Sie können den Storyboard-Ansatz vergessen und Ihre Einschränkungen stattdessen manuell hinzufügen. Da Sie dies in
viewDidLoad()
tun, gehe ich davon aus, dass die Absicht darin besteht, dies nur einmal für die gesamte Lebensdauer des Objekts zu tun, anstatt das Layout im laufenden Betrieb zu ändern. Daher sollte dies eine akzeptable Methode sein.quelle
Sie können die
priority
Eigenschaft auch so einstellen , dass sie aktiviert und deaktiviert wird (750 zum Aktivieren und 250 zum Deaktivieren). Aus irgendeinem Grund hatte das Ändern desactive
BOOL keine Auswirkungen auf meine Benutzeroberfläche. Keine Notwendigkeit fürlayoutIfNeeded
und kann bei viewDidLoad oder zu einem späteren Zeitpunkt festgelegt und geändert werden.quelle
viewWillTransition(to:, with:)
oderviewWillLayoutSubviews()
und Sie können alle alternativen Einschränkungen als "installiert" in einem Storyboard beibehalten. Die Einschränkungspriorität ändert sich möglicherweise nicht von nicht erforderlich zu erforderlich. Verwenden Sie daher die folgenden Werte1000
. Andererseits funktioniert das Aktivieren (Hinzufügen) und Deaktivieren (Entfernen) von Einschränkungen nur inviewDidLayoutSubviews()
und erfordert das Beibehalten vonstrong
@IBOutlet
Verweisen aufNSLayoutConstraint
-s.Der richtige Zeitpunkt, um nicht verwendete Einschränkungen zu deaktivieren:
Denken Sie daran, dass
viewWillLayoutSubviews
dies mehrmals aufgerufen werden kann, also keine schweren Berechnungen hier, okay?Hinweis: Wenn Sie einige der Einschränkungen später reaktivieren möchten, speichern Sie immer einen
strong
Verweis darauf.quelle
viewDidLayoutSubviews()
. Das Anpassen von Einschränkungen inviewWillLayoutSubviews()
funktioniert in meinem Fall nicht.Beim Erstellen einer Ansicht werden die folgenden Lebenszyklusmethoden der Reihe nach aufgerufen:
Nun zu Ihren Fragen.
Antwort: Wenn Sie versuchen, die Einschränkungen für die Ansichten in
viewDidLoad
der Ansicht festzulegen, gibt es keine Grenzen. Daher können keine Einschränkungen festgelegt werden. Erst danach sindviewDidLayoutSubviews
die Grenzen der Ansicht festgelegt.Antwort: Nein. Grund oben erläutert.
quelle
Ich habe festgestellt, solange Sie die Einschränkungen pro Normal in der Überschreibung von
- (void)updateConstraints
(Ziel c) mit einerstrong
Referenz für die verwendete Initialität aktive und nicht aktive Einschränkungen eingerichtet haben. Und an anderer Stelle im Ansichtszyklus deaktivieren und / oder aktivieren Sie, was Sie benötigen, und rufenlayoutIfNeeded
Sie dann an . Sie sollten keine Probleme haben.Die Hauptsache ist, die Überschreibung
updateConstraints
der Einschränkungen nicht ständig wiederzuverwenden und die Aktivierungen der Einschränkungen zu trennen, solange SieupdateConstraint
s nach Ihrer ersten Initialisierung und Ihrem ersten Layout aufrufen . Danach scheint es wichtig zu sein, wo im Ansichtszyklus.quelle