web-dev-qa-db-fra.com

Swift ajouter une contrainte par programme

J'ajoute une UILabel (amountLabel) dans UIViewController dans l'éditeur de storyboard. Et puis dans le fichier Swift, viewDidLoad, je crée par programme une UITextField (paymentTextField) et essaie d'ajouter une contrainte entre amountLabel et paymentTextField. Voici mon code dans viewDidload:

let paymentTextField = UITextField()
    paymentTextField.translatesAutoresizingMaskIntoConstraints = false
    paymentTextField.frame = CGRectMake(15, 100, CGRectGetWidth(self.view.frame) - 30, 44)
    self.view.addSubview(paymentTextField)

    let bottonConstraint = NSLayoutConstraint(item: paymentTextField, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: self.amountLabel , attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 30)
    bottonConstraint.identifier = "paymentTextFieldSpacing"
    NSLayoutConstraint.activateConstraints([bottonConstraint])

Mais je reçois une erreur:

"Application interrompue en raison d'une exception non interceptée 'NSGenericException', raison .__:" Impossible d'activer la contrainte avec les éléments> et> car ils n'ont pas d'ancêtre commun. La contrainte fait-elle référence à des éléments dans différentes hiérarchies de vues? illégal."

Est-ce que quelqu'un sait ce qui ne va pas? amountLabel est directement déplacé vers la vue dans le storyboard et "paymentTextField" est ajouté par programme à la même vue. Pourquoi n'ont-ils pas d'ancêtre commun?

24
jimshicard

J'ai rencontré le même problème que vous avez décrit plus tôt. Pour créer la sous-vue programmatique (dans votre cas, le paymentTextField), vous devez d'abord l'ajouter à la sous-vue, puis appliquer vos contraintes. 

En ajoutant la sous-vue à afficher en premier, les deux vues ont le même parent.

Très tard, mais espérons que cela aide quelqu'un d'autre.

100
Jamil Nawaz

Liste de contrôle pour ce numéro:

  • Vérifiez si vous avez ajouté la vue créée par programme à son parent avant d'activer des contraintes
  • Vérifiez si vous écrivez le code d'activation des contraintes dans viewDidLoad ()/viewWillAppear (). Vous devez écrire le code d'activation des contraintes dans updateViewConstraints ou viewWillLayoutSubviews. ( suggéré par vmeyer )
  • Vérifiez si vous désactivez translatesAutoresizingMaskIntoConstraints
15
Milan Kamilya

L'erreur indique que "parce qu'ils n'ont pas d'ancêtre commun", ce qui signifie qu'ils ne partagent pas le même parent. Afin de relier la contrainte entre deux éléments, ils doivent avoir une relation parent-enfant ou une relation fraternelle.

Dans votre cas, assurez-vous simplement qu'ils ont la même vue parent avant d'ajouter la contrainte par programme. 

9
Pauls

Assurez-vous d'avoir ajouté la paymentTextField à votre vue:

paymentTextField.translatesAutoResizingMaskIntoConstraints = false
view.addSubview(paymentTextField)

...

Ajoutez vos contraintes, par exemple paymentTextField.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true

3
happyhippie924
let nameLabel: UILabel = {

   let label = UILabel()
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
}()

si vous avez oublié de définir ce label.translatesAutoresizingMaskIntoConstraints = false ou si vous ajoutez une sous-vue après des contraintes .__, ce problème se pose