web-dev-qa-db-fra.com

Comment puis-je changer la priorité des contraintes au moment de l'exécution

J'ai une vue qui a une hauteur dynamique et j'essaie de changer cette priorité de hauteur de vue pendant l'exécution.

Voici ma partie de code;

if (index == 0) {

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

} else if (index == 1) {

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

}

Je change d'index avec une action de bouton. Lorsque j'exécute ce code, j'obtiens cette erreur:

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

Quelle est mon erreur ici?

63
Le'Kirdok

Comme indiqué dans NSLayoutConstraint référence de classe :

Les priorités ne peuvent pas passer de non requises à requises, ou de requises à non requises. Une exception sera levée si une priorité NSLayoutPriorityRequired sous OS X ou UILayoutPriorityRequired sous iOS est modifiée en priorité inférieure, ou si une priorité inférieure est modifiée en priorité requise après l'ajout des contraintes. à une vue. Le passage d'une priorité optionnelle à une autre priorité optionnelle est autorisé même après l'installation de la contrainte sur une vue.

Utilisez la priorité 999 au lieu de 1000. Cela ne sera pas absolument nécessaire sur le plan technique, mais ce sera une priorité plus élevée que toute autre chose.

140
Cyrille

Je veux faire un petit ajout à la réponse de Cyrille.

Si vous créez une contrainte dans le code, assurez-vous de définir sa priorité avant de l'activer. Par exemple:

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

Cela entraînerait une exception d'exécution.

La mutation d'une priorité de requis à non sur une contrainte installée (ou inversement) n'est pas prise en charge.

L'ordre correct est:

surveyViewHeightConstraint.priority = 999;
surveyViewHeightConstraint.active = YES;
34
Vipin

Nous avons toujours géré cela en ne modifiant pas la constante de contrainte, mais simplement la priorité. Par exemple, dans votre situation, vous devez respecter deux contraintes de hauteur.

 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)

si vous voulez masquer la vue, vous:

heightConstraintTwo.priority = 999;

de même, si vous souhaitez afficher la vue:

heightConstraintTwo.priority = 250;
6
J Andrew McCormick

Version rapide:

myContraint.priority = UILayoutPriority(999.0)
4
Alexey

J'espère que ce scénario aidera quelqu'un: j'avais deux contraintes, elles étaient opposées l'une à l'autre, je veux dire qu'elles ne pouvaient pas être satisfaites en même temps, dans le constructeur d'interface, l'un d'entre eux avait la priorité 1 000 et l'autre moins de 1 000. quand je les ai changés dans le code, j'ai eu cette erreur:

Application interrompue en raison d'une exception non interceptée 'NSInternalInconsistencyException', motif: 'La mutation d'une priorité de requis à non sur une contrainte installée (ou inversement) n'est pas prise en charge. Vous avez passé la priorité 250 et la priorité existante était 1000.'

alors je viens de les initialiser dans la fonction viewDidLoad avec les valeurs .defaultHigh et .defaultLow et cela a résolu mon problème.

2

Selon NSLayoutConstraints class à l'intérieur UIKit Module

Si le niveau de priorité d'une contrainte est inférieur à UILayoutPriorityRequired, il est facultatif. Les contraintes de priorité supérieure sont satisfaites avant les contraintes de priorité inférieure. La satisfaction de contrainte n'est pas tout ou rien. Si une contrainte 'a == b' est optionnelle, cela signifie que nous tenterons de minimiser 'abs (a-b)'. Cette propriété ne peut être modifiée que dans le cadre de la configuration initiale ou lorsqu'elle est facultative. Après l'ajout d'une contrainte à une vue, une exception sera levée si la priorité est changée de/en NSLayoutPriorityRequired.

Exemple: - UIButton contraintes avec différentes priorités -

 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])

         }  
1
Jack

Maintenant, vous pouvez simplement prendre la connexion IBOutlet pour vos contraintes, puis utiliser ce code.

self.webviewHeight.priority = UILayoutPriority(rawValue: 1000)
0
Kishore Kumar