LCB
LCB

Reputation: 1050

Swift get error when addConstraints for a UITextField with Visual Format Language

I want to add an UITextField into an UITableCell and set both it's width and height 100%;

My swift code :

nameTextField.translatesAutoresizingMaskIntoConstraints = false

addSubview( nameTextField )    

let views = [
    "name" : nameTextField
];

let widthLayoutConstraint = NSLayoutConstraint.constraintsWithVisualFormat( "H:|-[name]-|", options: [], metrics: nil, views: views )
nameTextField.addConstraints( widthLayoutConstraint )
let heightLayoutConstraint = NSLayoutConstraint.constraintsWithVisualFormat( "V:|-[name]-|", options: [], metrics: nil, views: views )
nameTextField.addConstraints( heightLayoutConstraint )

I got the follow error message while the table will show:

2016-07-31 19:16:43.027 NOIB[40193:1889520] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to install constraint on view.  Does the constraint reference something from outside the subtree of the view?  That's illegal. constraint:<NSLayoutConstraint:0x7ffbfa70f480 UITextField:0x7ffbfa41dff0.leading == NOIB.NameCell:0x7ffbfa41da10'NameCell'.leadingMargin> view:<UITextField: 0x7ffbfa41dff0; frame = (0 0; 0 0); text = ''; clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x7ffbfa41e5c0>>'

Upvotes: 0

Views: 302

Answers (1)

vacawama
vacawama

Reputation: 154631

It's odd that you are calling addSubview without specifying a view. Usually it is used like:

cell.contentView.addSubview(nameTextField)

Since you aren't specifying a view, then it must be using self.

Two views are involved in the constraints that are returned by your VFL: your nameTextField and its superview. In VFL, "|" represents the superview so it doesn't have to be explicitly included in the view dictionary that you pass in. You need to add the constraints to the view that is higher in the hierarchy. In your case, you need to add the constraints to the superview of nameTextField, which is self. So you could probably do:

self.addConstraints(widthLayoutConstraint)
self.addConstraints(heightLayoutConstraint)

As of iOS 8, there is an easier way. The constraints know which views they need to be added to, so you just have to set their active properties to true. VFL can return multiple constraints, so you need to make all of them active. You can use the class method activateConstraints of NSLayoutConstraint to activate multiple constraints:

let widthLayoutConstraint = NSLayoutConstraint.constraintsWithVisualFormat( "H:|-[name]-|", options: [], metrics: nil, views: views )
NSLayoutConstraint.activateConstraints(widthLayoutConstraint)
let heightLayoutConstraint = NSLayoutConstraint.constraintsWithVisualFormat( "V:|-[name]-|", options: [], metrics: nil, views: views )
NSLayoutConstraint.activateConstraints(heightLayoutConstraint)

Upvotes: 2

Related Questions