web-dev-qa-db-fra.com

Création par programme de contraintes liées à l'affichage des marges du contrôleur

J'essaie de créer une vue qui agira comme une sorte de "panneau", attachée au côté droit du contrôleur de vue. 

Autrement dit, il est lié aux marges de fin, supérieure et inférieure du contrôleur de vue parent, avec une largeur statique de 300.

Cependant, je n'arrive tout simplement pas à comprendre, je suis en train de casser une contrainte ou de faire quelque chose que xcode dit illégal. 

Qu'est-ce que je fais mal?

Voici le code dans le contrôleur

    let myView = UIView()
    view.backgroundColor = UIColor.redColor()
    self.view.addSubview(view)
    let topConstraint = NSLayoutConstraint(item: myView,
                                           attribute: .Top,
                                           relatedBy: .Equal,
                                           toItem: self.topLayoutGuide,
                                           attribute: .Bottom,
                                           multiplier: 1,
                                           constant: 0)

    let trailingConstraint = NSLayoutConstraint(item: self.view,
                                                attribute: .TrailingMargin,
                                                relatedBy: .Equal,
                                                toItem: myView,
                                                attribute: .Trailing,
                                                multiplier: 1,
                                                constant: 0)

    let bottomConstraint = NSLayoutConstraint(item: self.bottomLayoutGuide,
                                              attribute: .Top,
                                              relatedBy: .Equal,
                                              toItem: myView,
                                              attribute: .Bottom,
                                              multiplier: 1,
                                              constant: 0)

    let widthConstraint = NSLayoutConstraint(item: myView,
                                             attribute: .Width,
                                             relatedBy: .Equal,
                                             toItem: nil,
                                             attribute: .NotAnAttribute,
                                             multiplier: 1,
                                             constant: 300)

    self.view.addConstraints([trailingConstraint])
    view.addConstraints([topConstraint, bottomConstraint, widthConstraint])
13
prawn

En réalité, le problème dans votre code est que vous n'avez pas défini la variable translatesAutoresizingMaskIntoConstraints de myview sur false, chaque fois que vous souhaitez utiliser des contraintes de présentation automatique, vous devez définir la variable translatesAutoresizingMaskIntoConstraints d'une vue sur false ..__ ajoutez myview sur self.view J'ai mis à jour votre code et il fonctionne parfaitement en fonction de vos contraintes.

Mettez le code ci-dessous dans votre ViewController.

let myView = UIView()
myView.backgroundColor = UIColor.redColor()
self.view.addSubview(myView)
myView.translatesAutoresizingMaskIntoConstraints = false

view.addConstraint(NSLayoutConstraint(item: myView, attribute: .Top, relatedBy: .Equal, toItem: self.topLayoutGuide, attribute: .Bottom, multiplier: 1, constant: 0))
view.addConstraint(NSLayoutConstraint(item: myView, attribute: .Bottom, relatedBy: .Equal, toItem: self.bottomLayoutGuide, attribute:.Top, multiplier: 1, constant: 20))

view.addConstraint(NSLayoutConstraint(item: myView, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute,multiplier: 1, constant: 300))
view.addConstraint(NSLayoutConstraint(item: myView, attribute: .TrailingMargin, relatedBy: .Equal, toItem: view, attribute: .TrailingMargin, multiplier: 1, constant: 0))
48

Dans votre exemple de code ci-dessus, il semble que vous mélangez view et myView à quelques endroits. Quoi qu'il en soit, widthConstraint doit être ajouté à myView et topConstraint, trailingConstraint et bottomConstraint doivent être ajoutés à self.view. La raison en est que des contraintes doivent être ajoutées à l'ancêtre superview le plus proche, qui expose les deux vues impliquées dans la contrainte. Dans le cas où vous contraignez un attribut de vue enfant à un attribut de sa vue parent, la contrainte doit être ajoutée à la vue parent, car elle présente à la fois elle-même et la vue enfant. Si vous avez une contrainte entre deux vues jumelles, elle sera ajoutée à la vue parent car c'est l'ancêtre le plus proche qui affiche les deux vues impliquées.

Si vous êtes en mesure de cibler iOS 9.0 et les versions ultérieures, il est beaucoup plus simple et plus propre d'utiliser les nouveaux API NSLayoutAnchor et NSLayoutDimension pour créer ce type de contraintes. Il fournit également une vérification de type stricte et le compilateur peut vérifier son exactitude. Avec ces nouvelles API, votre exemple de code deviendrait simplement:

let myView = UIView()
myView.backgroundColor = UIColor.redColor()
self.view.addSubview(myView)

let margins = self.view.layoutMarginsGuide
myView.trailingAnchor.constraintEqualToAnchor(margins.trailingAnchor).active = true
myView.topAnchor.constraintEqualToAnchor(margins.topAnchor).active = true
myView.bottomAnchor.constraintEqualToAnchor(margins.bottomAnchor).active = true
myView.widthAnchor.constraintEqualToConstant(300.0).active = true

Il n'est pas nécessaire d'ajouter explicitement les contraintes à la vue de droite, etc. Vous pouvez en savoir plus sur cette méthode de création de contraintes ici: 

https://developer.Apple.com/library/ios/documentation/AppKit/Reference/NSLayoutAnchor_ClassReference/

et ici:

https://developer.Apple.com/library/ios/documentation/AppKit/Reference/NSLayoutDimension_ClassReference/

9
Daniel Hall

Il semble y avoir une certaine ambiguïté dans votre code, vous créez une UIView en tant que myView mais ajoutez view à self.view et même une contrainte pour s’afficher. Donc corrigez votre code et remplacez view par myView . Deuxièmement, setTranslayesAutoresizingMaskIntoConstraints to false . Ajoutez ensuite toutes les contraintes à self.view. Cela devrait résoudre votre problème.

 myView.setTranslatesAutoresizingMaskIntoConstraints(false)
 self.view.addConstraints([trailingConstraint, bottomConstraint, widthConstraint])

VFL est également une approche meilleure et propre. Cela donne en fait une visualisation de la configuration des contraintes. 

0
Arun Gupta