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?
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 ouUILayoutPriorityRequired
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.
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;
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;
Version rapide:
myContraint.priority = UILayoutPriority(999.0)
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.
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])
}
Maintenant, vous pouvez simplement prendre la connexion IBOutlet pour vos contraintes, puis utiliser ce code.
self.webviewHeight.priority = UILayoutPriority(rawValue: 1000)