2013-10-15 1 views
67

Ich sehe verschiedene Beispiele, wo 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.Wo sollte ich automatische Layout-Einschränkungen beim Erstellen von Sichten programmgesteuert setzen

Wenn ich versuche, Einschränkungen in updateViewContraints zu setzen, kann es eine Sprunghaftigkeit im Layout geben, z. leichte Verzögerung, bevor die Ansicht erscheint. Wenn ich diese Methode verwende, sollte ich auch zuerst die bestehenden Einschränkungen beseitigen, d. H. [self.view [removeConstraints:self.view.constraints]?

+1

ich die gleiche Erfahrung mit updateViewConstraints gehabt haben, so Ich habe aufgehört zu versuchen, es zu benutzen. Ich konfiguriere Constraints in ViewDidLoad oder in der Methode updateConstraints einer benutzerdefinierten Ansicht. Hoffentlich gibt dir jemand eine definitive Antwort. – bilobatum

+1

'updateViewConstraints': * Sie können diese Methode in einer Unterklasse überschreiben, um der Ansicht oder ihren Unteransichten Einschränkungen hinzuzufügen. * (Aus den [Apple-Dokumenten] (https://developer.apple.com/library/ios/documentation /Uikit/reference/UIViewController_Class/index.html#//apple_ref/occ/instm/UIViewController/updateViewConstraints)) – testing

Antwort

94

Ich habe meine Einschränkungen in viewDidLoad/loadView eingerichtet (ich bin auf iOS> = 6). updateViewConstraints ist nützlich zum Ändern von Werten von Beschränkungen, z.B. Wenn eine Abhängigkeit von der Ausrichtung des Bildschirms abhängig ist (ich weiß, es ist eine schlechte Übung), können Sie in dieser Methode ihre constant ändern.

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

UPDATE: ich die Erwähnung der Einrichtung Einschränkungen in Resource Management in View Controllers bemerkt haben:

Wenn Sie es vorziehen erstellen Ansichten programmatisch, anstatt mit einem Storyboard, tun Sie dies durch zwingende Ihre Ansicht Controller loadView Methode. Ihre Implementierung dieser Methode sollte wie folgt vorgehen:

(...)

3. Wenn Sie Auto-Layout verwenden, assign ausreichend Einschränkungen jeweils die Ansichten, die Sie nur die Position geschaffen zu steuern und Größe Ihrer Ansichten. Andernfalls implementieren Sie die Methoden viewWillLayoutSubviews und viewDidLayoutSubviews, um die Frames der Unteransichten in der Ansichtshierarchie anzupassen. Siehe „Ändern der Größe, die Ansichten des View-Controller.“

UPDATE 2: Während der WWDC 2015 Apple gave a new explanation von updateConstraints und updateViewConstraints Verwendung empfohlen:

Wirklich, das alles ist ein Weg für Ansichten ein haben Chance, rechtzeitig Änderungen für den nächsten Layout-Durchlauf vorzunehmen, aber es wird oft nicht benötigt.

All Ihre anfängliche Constraint-Einrichtung sollte idealerweise im Interface Builder erfolgen.

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

Update-Einschränkungen sind nur für die Arbeit, die regelmäßig wiederholt werden muss.

Es ist auch ziemlich einfach, Einschränkungen zu ändern, wenn Sie die Notwendigkeit dazu finden; Wenn Sie diese Logik jedoch von dem anderen Code, der damit in Beziehung steht, entfernen und ihn in eine separate Methode verschieben, die zu einem späteren Zeitpunkt ausgeführt wird, wird es viel schwieriger, Ihrem Code zu folgen. Daher wird es schwieriger für Sie, ihn zu pflegen Es wird für andere Menschen viel schwieriger sein zu verstehen.

Also, wann müssten Sie Update-Einschränkungen verwenden?

Nun, es läuft auf die Leistung.

Wenn Sie feststellen, dass das Ändern nur der Constraints zu langsam ist, können Ihnen Update-Constraints helfen.

Es stellt sich heraus, dass das Ändern einer Integritätsbedingung in Aktualisierungsbedingungen tatsächlich schneller ist als das Ändern einer Integritätsbedingung zu anderen Zeitpunkten.

Der Grund dafür ist, dass die Engine in der Lage ist, alle in diesem Durchlauf auftretenden Constraint-Änderungen als Batch zu behandeln.

+2

+1 für diese als die beste Antwort. Apple schreibt loadView als den richtigen Platz zum Setzen von Anfangseinschränkungen vor, und dies erfordert kein zusätzliches BOOL-Flag in der updateConstraints-Methode (was einfach hacky zu sein scheint). – awolf

+4

Meiner Meinung nach sollte die Ansicht für die Einschränkungen verantwortlich sein, nicht der View-Controller. In vielen Fällen weiß der View-Controller sogar nicht, was alle Elemente in der Ansicht sind (zum Beispiel statische Labels in einer Tabellenansichtszelle). – dasdom

+1

@dasdom Wie kann die Ansicht ihre Beziehung zu anderen Ansichten steuern? Du musst im ViewController Constraints wie '@" | - [button1] - [button2] - | "' setzen, oder? Oder gibt es einen anderen Weg? – Joseph

31

Ich empfehle einen BOOL zu schaffen und sie im -updateConstraints von UIView (oder -updateViewConstraints, für UIViewController) einstellen.

-[UIView updateConstraints]: (Apfel docs)

Benutzerdefinierte Ansichten, die Einschränkungen einrichten sich durch Überschreiben dieser Methode tun sollte.

Sowohl -updateConstraints und -updateViewConstraints können mehrmals im Laufe eines Lebens nach Ansicht aufgerufen werden. (Wenn Sie beispielsweise in einer Ansicht setNeedsUpdateConstraints aufrufen, wird dies ausgelöst.) Daher müssen Sie sicherstellen, dass doppelte Constraints nicht erstellt und aktiviert werden - entweder mit einem BOOL, um bestimmte Constraint-Setups nur einmal auszuführen, oder mit make vor dem Erstellen von & vorhandene neue Einschränkungen deaktivieren/entfernen.

Zum Beispiel:

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

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

Beifall für den Hinweis auf in den Kommentaren @fresidue, dass Apples docs Aufruf super als letzten Schritt empfehlen. Wenn Sie vor dem Ändern einiger Einschränkungen super aufrufen, können Sie eine Laufzeitausnahme (Absturz) treffen.

+6

Ich bin nicht sicher, ob es einen pragmatischen Unterschied macht, aber die Dokumentation sagt 'Wichtig: Call [super updateConstraints] als letzten Schritt in Ihrer Implementierung.' – fresidue

+0

Prost du, ich werde meine Antwort aktualisieren. – BooRanger

+0

Gemäß den Dokumenten, wenn Sie eine Ansicht zur Laufzeit ändern und Ihre Einschränkungen ungültig machen, entfernt das System diese Einschränkung sofort und ruft setNeedsUpdateConstraints auf. Bevor ein neues Layout ausgeführt wird, ruft das System updateConstraints auf, in denen Sie das ungültige Layout anpassen können. Daher würde ich wahrscheinlich keine Markierung für diese Methode setzen, die das System daran hindern könnte, sie aufzurufen. – smileBot

0

Ich habe diese Lösung, um Einschränkungen zu ändern, bevor diejenigen, die im Storyboard geladen sind, 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! 
} 
0

Sie können sie in viewWillLayoutSubviews gesetzt: zu:

override func viewWillLayoutSubviews() { 

    if(!wasViewLoaded){ 
     wasViewLoaded = true 

     //update constraint 

     //also maybe add a subview    
    } 
} 
0

Tun Sie es im Hinblick tat Layout Subviews Methode

override func viewDidLayoutSubviews() { 
    super.viewDidLayoutSubviews() 
} 
Verwandte Themen