it-swarm.com.de

Wo sollte ich Autolayout-Einschränkungen festlegen, wenn Ansichten programmgesteuert erstellt werden

Ich sehe verschiedene Beispiele, in denen Einschränkungen festgelegt sind. Einige setzen sie in viewDidLoad/loadView (nachdem die Unteransicht hinzugefügt wurde). Andere setzen sie in der Methode updateViewConstraints, die von viewDidAppear aufgerufen wird.

Wenn ich versuche, Einschränkungen in updateViewContraints festzulegen, kann das Layout sprunghaft sein, z. leichte Verzögerung, bevor die Ansicht erscheint. Wenn ich diese Methode verwende, sollte ich auch vorhandene Einschränkungen zuerst löschen, d. H. [self.view [removeConstraints:self.view.constraints]?

74
Heisenberg

Ich richte meine Einschränkungen in viewDidLoad/loadView ein (ich wende iOS> = 6 an). updateViewConstraints ist nützlich zum Ändern von Werten von Beschränkungen, z. Wenn eine Einschränkung von der Ausrichtung des Bildschirms abhängt (ich weiß, es ist eine schlechte Praxis), können Sie deren constant in dieser Methode ändern.

Das Hinzufügen von Einschränkungen in viewDidLoad wird während der Sitzung "Einführung in das automatische Layout für iOS und OS X" (WWDC 2012) ab 39 gezeigt : 22. Ich denke, es ist eines der Dinge, die während der Vorlesungen gesagt werden, aber nicht in der Dokumentation landen.

UPDATE: Ich habe die Erwähnung des Einrichtens von Einschränkungen in der Ressourcenverwaltung in View Controllern bemerkt :

Wenn Sie Ansichten lieber programmgesteuert erstellen möchten, anstatt ein Storyboard zu verwenden, müssen Sie die loadView -Methode Ihres Ansichtscontrollers überschreiben. Ihre Implementierung dieser Methode sollte Folgendes tun:

(...)

3.Wenn Sie das automatische Layout verwenden, weisen Sie jeder der soeben erstellten Ansichten ausreichende Einschränkungen zu, um die Position und Größe Ihrer Ansichten zu steuern . Implementieren Sie andernfalls die Methoden viewWillLayoutSubviews und viewDidLayoutSubviews, um die Frames der Unteransichten in der Ansichtshierarchie anzupassen. Siehe "Ändern der Größe der Ansichten des View Controllers".

UPDATE 2 : Während der WWDC 2015 gab Apple eine neue Erklärung für updateConstraints und updateViewConstraints empfohlene Verwendung:

Auf diese Weise haben Ansichten die Möglichkeit, Änderungen an Einschränkungen rechtzeitig für den nächsten Layoutdurchlauf vorzunehmen, was jedoch häufig nicht erforderlich ist.

Die Einrichtung aller anfänglichen Einschränkungen sollte idealerweise in Interface Builder erfolgen.

Oder wenn Sie wirklich feststellen, dass Sie Ihre Einschränkungen programmgesteuert zuweisen müssen, ist ein Ort wie viewDidLoad viel besser.

Update-Einschränkungen gelten nur für Arbeiten, die regelmäßig wiederholt werden müssen.

Außerdem ist es ziemlich einfach, Einschränkungen zu ändern, wenn Sie dies tun müssen. Wenn Sie diese Logik von dem anderen Code, der damit zusammenhängt, trennen und sie in eine separate Methode verschieben, die zu einem späteren Zeitpunkt ausgeführt wird, ist es sehr viel schwieriger, dem Code zu folgen, sodass es für Sie schwieriger wird, ihn zu warten , wird es für andere Leute viel schwieriger zu verstehen sein.

Wann müssen Sie Update-Einschränkungen verwenden?

Nun, es läuft auf Leistung hinaus.

Wenn Sie der Meinung sind, dass es zu langsam ist, nur die vorhandenen Einschränkungen zu ändern, können Sie mithilfe von Update-Einschränkungen Abhilfe schaffen.

Es stellt sich heraus, dass das Ändern einer Einschränkung innerhalb von Aktualisierungseinschränkungen tatsächlich schneller ist als das Ändern einer Einschränkung zu anderen Zeiten.

Der Grund dafür ist, dass die Engine alle in diesem Durchlauf auftretenden Änderungen der Integritätsbedingungen als Batch behandeln kann.

102
Arek Holko

Ich empfehle, eine BOOL zu erstellen und sie in den -updateConstraints von UIView (oder -updateViewConstraints für UIViewController) zu setzen. 

-[UIView updateConstraints] : (Apple-Dokumente)

Benutzerdefinierte Ansichten, die selbst Einschränkungen festlegen, sollten diese Methode überschreiben.

Sowohl -updateConstraints als auch -updateViewConstraints können während der Lebensdauer einer Ansicht mehrmals aufgerufen werden. (Durch Aufruf von setNeedsUpdateConstraints für eine Ansicht wird dies beispielsweise ausgelöst.) Als Ergebnis müssen Sie das Erstellen und Aktivieren von doppelten Abhängigkeiten verhindern. Entweder verwenden Sie eine BOOL, um nur ein bestimmtes Constraint-Setup nur einmal auszuführen, oder indem Sie dies tun Stellen Sie sicher, dass vorhandene Einschränkungen deaktiviert/entfernt werden, bevor Sie neue erstellen und aktivieren.

Zum Beispiel:

  - (void)updateConstraints {  // for view controllers, use -updateViewConstraints

         if (!_hasLoadedConstraints) {
              _hasLoadedConstraints = YES;
             // create your constraints
         }
         [super updateConstraints];
    }

Prost an @fresidue in den Kommentaren, um darauf hinzuweisen, dass die Dokumente von Apple den Aufruf von super als letzten Schritt empfehlen. Wenn Sie super aufrufen, bevor Sie an einigen Einschränkungen Änderungen vornehmen, kann es zu einer Laufzeitausnahme (Absturz) kommen.

31
BooRanger

Dies sollte in ViewDidLoad gemäß WWDC-Video von Apple und der Dokumentation erfolgen. 

Keine Ahnung, warum Leute UpdateConstraints empfehlen. Wenn Sie dies in updateConstraints tun, treten bei NSAutoresizingMaskLayoutConstraint Probleme mit der automatischen Größenanpassung auf, da Ihre Ansichten die automatischen Masken bereits berücksichtigt haben. Sie müssen sie in updateConstraints entfernen, damit sie funktionieren. 

UpdateConstraints sollte genau das sein, wenn Sie sie "aktualisieren" müssen, Änderungen an Ihrem ursprünglichen Setup vornehmen müssen.

4
BluelineCoding

Sie können sie in viewWillLayoutSubviews einstellen: zu:

 override func viewWillLayoutSubviews() {

    if(!wasViewLoaded){
        wasViewLoaded = true

        //update constraint

        //also maybe add a subview            
    }
}
1
Andre Simon

Ich habe diese Lösung, um Einschränkungen zu ändern, bevor diejenigen, die sich im Storyboard befinden, geladen werden. Diese Lösung entfernt alle Verzögerungen, nachdem die Ansicht geladen wurde.

-(void)updateViewConstraints{

    dispatch_async(dispatch_get_main_queue(), ^{

            //Modify here your Constraint -> Activate the new constraint and deactivate the old one

            self.yourContraintA.active = true;
            self.yourContraintB.active= false;
            //ecc..
           });

    [super updateViewConstraints]; // This must be the last thing that you do here -> if! ->Crash!
}
1
Davide

Tun Sie es in View Did Layout Subviews-Methode

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
}
1
Kit

Das hat für mich funktioniert:

Swift 4.2

override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

// Modify your constraints in here

  ...

}

Ehrlich gesagt bin ich mir nicht sicher, ob es das wert ist. Es scheint etwas langsamer als in viewDidLoad () zu laden. Ich wollte sie nur aus dem letzteren entfernen, weil es massiv wird.

0