web-dev-qa-db-fra.com

Comment changer la contrainte de mise en page par programme dans Swift?

J'ai une vue de collection qui a un TextView pour chaque cellule. Ceci est ma contrainte textview configurée

textView.topAnchor.constraint(equalTo: object1.bottomAnchor).isActive = true
textView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true

... et la largeur et la hauteur de mon textView.

Maintenant, je veux changer topAnchor de mon textView en ancre inférieure d'objet 2 au lieu d'ancre inférieure d'objet 1 en raison d'une condition if. Cependant, lorsque j'entre le code ci-dessous, je reçois Will tentera de récupérer en cassant l'erreur de contrainte.

Quelqu'un sait-il comment changer l'ancre supérieure une fois qu'elle est déjà configurée?

if (aCondition){
textView.topAnchor.constraint(equalTo: object2.bottomAnchor).isActive = true
}else{
  textView.topAnchor.constraint(equalTo: object1.botttomAnchor).isActive = true
}
7
KevinVuD

Vous devez désactiver l'ancienne contrainte active. Pour l'instant, vous ajoutez simplement de nouvelles contraintes à la vue. Donc, je vous suggère d'abord de créer deux propriétés qui conserveraient les références aux contraintes:

fileprivate var topConstraint1: NSLayoutConstraint?
fileprivate var topConstraint2: NSLayoutConstraint?

Puis au début, lorsque vous créez l'interface utilisateur, initialisez-les correctement:

topConstraint1 = textView.topAnchor.constraint(equalTo: object1.bottomAnchor)
topConstraint2 = textView.topAnchor.constraint(equalTo: object2.bottomAnchor)

Et activez celui que vous souhaitez être actif en premier:

topConstraint1?.isActive = true

Ensuite, lorsque vous souhaitez modifier les contraintes, vous désactivez d'abord celle qui doit être désactivée, puis activez la bonne:

if aCondition {
    topConstraint1?.isActive = false
    topConstraint2?.isActive = true
} else {
    topConstraint2?.isActive = false
    topConstraint1?.isActive = true
}

P.S .: Vous voulez toujours d'abord désactiver l'ancien, puis activer le nouveau, sinon à ce moment-là, lorsque vous activez le nouveau, cela entrerait en conflit avec l'ancien et provoquerait des avertissements dans la console.

P.S.2: Si vous souhaitez activer plusieurs contraintes à la fois, utilisez NSLayoutConstraint.activate(_:) - selon documentation , c'est plus efficace:

En règle générale, l'utilisation de cette méthode est plus efficace que l'activation individuelle de chaque contrainte.

Par exemple, au lieu de:

someConstraint1.isActive = true
someConstraint2.isActive = true

utilisez plutôt:

NSLayoutConstraint.activate([someConstraint1, someConstraint2])

Il en va de même pour la désactivation des contraintes et NSLayoutConstraint.deactivate(_:) .

22
Milan Nosáľ