2015-07-02 10 views
36

Ich habe eine Ansicht, die dynamische Höhe hat und ich versuche, diese Ansichtshöhepriorität in der Laufzeit zu ändern.Wie kann ich Constraints Priorität in Laufzeit ändern

Hier ist mein Teil des Codes;

if (index == 0) { 

    surveyViewHeightConstraint.constant = 0; 
    surveyViewHeightConstraint.priority = 1000; 

} else if (index == 1) { 

    surveyViewHeightConstraint.constant = 163; 
    surveyViewHeightConstraint.priority = 500; 

} 

Ich ändere den Index mit einer Schaltfläche Aktion. Wenn ich diesen Code ausführen, bin ich diesen Fehler:

*** Assertion failure in -[NSLayoutConstraint setPriority:], /SourceCache/Foundation/Foundation-1141.1/Layout.subproj/NSLayoutConstraint.m:174 

Was hier mein Fehler ist?

Antwort

93

Wie in NSLayoutConstraint class reference erklärte:

Priorities may not change from nonrequired to required, or from required to nonrequired. An exception will be thrown if a priority of NSLayoutPriorityRequired in OS X or UILayoutPriorityRequired in iOS is changed to a lower priority, or if a lower priority is changed to a required priority after the constraints is added to a view. Changing from one optional priority to another optional priority is allowed even after the constraint is installed on a view.

Verwenden Priorität 999 anstelle von 1000. Es wird nicht unbedingt technisch gesehen erforderlich sein, aber es wird eine höhere Priorität als alles andere sein.

+2

Vielen Dank für Ihre nette Antwort, aber wenn ich 999 anstelle von 1000 verwende, kann ich meine Ansicht nicht verbergen, indem ich der Beschränkung der Höhe 0 gebe. –

+0

Das ist ein anderes Problem. Möglicherweise haben Sie andere widersprüchliche Einschränkungen. Wenn der Code nicht mehr abstürzt, die Ansichtsanimation jedoch immer noch nicht korrekt ist, markieren Sie diese Frage als gelöst. dann öffne einen anderen. – Cyrille

5

Die Art und Weise, wie wir dies immer gehandhabt haben, besteht darin, die Constraint-Konstante nicht zu ändern, sondern nur die Priorität. Zum Beispiel haben Sie in Ihrer Situation zwei Höhenbeschränkungen.

heightConstraintOne (who's height is set in the storyboard at 150, and priority set at 750) 
heightConstraintTwo (who's height is set in the storyboard at 0, and priority set at 250) 

wenn Sie die Ansicht ausblenden möchten, können Sie:

heightConstraintTwo.priority = 999; 

ebenfalls, wenn Sie die Ansicht angezeigt werden soll:

heightConstraintTwo.priority = 250; 
+0

Cool, hab's: nutze 999 statt 1000. Danke – brainray

18

Ich möchte dafür eine kleine Ergänzung zu Cyrille des Antworten.

Wenn Sie eine Einschränkung im Code erstellen, stellen Sie sicher, dass Sie die Priorität festlegen, bevor Sie sie aktivieren. Zum Beispiel:

surveyViewHeightConstraint = [NSLayoutConstraint constraintWithItem:self 
               attribute:NSLayoutAttributeHeight 
               relatedBy:NSLayoutRelationEqual 
                toItem:self.superview 
               attribute:NSLayoutAttributeHeight 
               multiplier:1 
               constant:0]; 
surveyViewHeightConstraint.active = YES; 
surveyViewHeightConstraint.priority = 999; 

Dies würde Run-Time-Ausnahme führen.

Mutating a priority from required to not on an installed constraint (or vice-versa) is not supported.

richtige Reihenfolge ist:

surveyViewHeightConstraint.priority = 999; 
surveyViewHeightConstraint.active = YES; 
1

Nach NSLayoutConstraints class innen UIKit Module

If a constraint's priority level is less than UILayoutPriorityRequired, then it is optional. Higher priority constraints are met before lower priority constraints. Constraint satisfaction is not all or nothing. If a constraint 'a == b' is optional, that means we will attempt to minimize 'abs(a-b)'. This property may only be modified as part of initial set up or when optional. After a constraint has been added to a view, an exception will be thrown if the priority is changed from/to NSLayoutPriorityRequired.

Beispiel: - UIButton Constraints mit verschiedenen Prioritäten -

func setConstraints() { 
     buttonMessage.translatesAutoresizingMaskIntoConstraints = false 
     NSLayoutConstraint(item: buttonMessage, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1.0, constant: -10).isActive = true 

     let leading = NSLayoutConstraint(item: buttonMessage, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1.0, constant: 10) 

     leading.isActive = true 


     let widthConstraint = NSLayoutConstraint(item: buttonMessage, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100) 

     let heightConstraint = NSLayoutConstraint(item: buttonMessage, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 50) 


     let trailingToSuperView = NSLayoutConstraint(item: buttonMessage, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1, constant: 0) 

     trailingToSuperView.priority = 999 
     trailingToSuperView.isActive = true 

     //leading.isActive = false//uncomment & check it will align to right of the View 

     buttonMessage.addConstraints([widthConstraint,heightConstraint]) 

     } 
+0

Nein, du solltest nie in 'viewDidLayoutSubviews' Einschränkungen erzeugen. Diese Methode kann mehrmals aufgerufen werden, wodurch Ihre App zum Absturz gebracht werden kann, wenn Sie dort doppelte Constraints erstellen. – mph

+0

@mph wahr! Ich habe die Antwort bearbeitet. – Jack

Verwandte Themen