user1094081
user1094081

Reputation:

Setting autolayout constraints causes 'Unable to simultaneously satisfy constraints' error

First time I set AutoLayout constraints of a view using code (I need a dynamic view to be created in different viewControllers and I prefer to create this UIView "on the fly").

My UIView should be attached to the superview top, as large as the superview and the bottom should be attached to the top of a particular view (navigationbar).

I tried the following:

let newView = UIView()
newView.backgroundColor = UIColor.red
view.addSubview(newView)

newView.translatesAutoresizingMaskIntoConstraints = false

let verticalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerY, multiplier: 1, constant: 0)

let widthConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: view,attribute: NSLayoutAttribute.width, multiplier: 1, constant: 0)

let bottomConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: navigationBar, attribute: NSLayoutAttribute.top, multiplier: 1, constant: 0)

NSLayoutConstraint.activate([verticalConstraint, widthConstraint, bottomConstraint])

I get the following runtime error but I can't understand what's the constraint that is not useful: I have a manually created view with identical constraints (there's one more too) and I get no errors:

[LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<NSLayoutConstraint:0x60800009d060 UINavigationBar:0x7f8061c0d2b0.top == UILayoutGuide:0x6080001ace80'UIViewSafeAreaLayoutGuide'.top   (active)>",
    "<NSLayoutConstraint:0x60400008fc80 UIView:0x7f8061f13b20.centerY == UIView:0x7f8061c17ce0.centerY   (active)>",
    "<NSLayoutConstraint:0x60400008faa0 UIView:0x7f8061f13b20.bottom == UINavigationBar:0x7f8061c0d2b0.top   (active)>",
    "<NSLayoutConstraint:0x60000009b120 'UIView-Encapsulated-Layout-Height' UIView:0x7f8061c17ce0.height == 667   (active)>",
    "<NSLayoutConstraint:0x60800009d0b0 'UIViewSafeAreaLayoutGuide-top' V:|-(20)-[UILayoutGuide:0x6080001ace80'UIViewSafeAreaLayoutGuide']   (active, names: '|':UIView:0x7f8061c17ce0 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x60400008fc80 UIView:0x7f8061f13b20.centerY == UIView:0x7f8061c17ce0.centerY   (active)>

Any help is appreciated

Upvotes: 0

Views: 372

Answers (2)

mrc
mrc

Reputation: 521

You don't need to use a constraint for the centerY property. Since you aim is to pin the view to the top, try using a topAnchor constraint and make it equal to superview.topAnchor. Hope this helps:

let newView = UIView()
newView.backgroundColor = UIColor.red
view.addSubview(newView)

newView.translatesAutoresizingMaskIntoConstraints = false

let topConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.topAnchor, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.topAnchor, multiplier: 1, constant: 0)

let widthConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: view,attribute: NSLayoutAttribute.width, multiplier: 1, constant: 0)

let bottomConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: navigationBar, attribute: NSLayoutAttribute.top, multiplier: 1, constant: 0)

NSLayoutConstraint.activate([verticalConstraint, widthConstraint, bottomConstraint])

Upvotes: 0

Explorer.AS
Explorer.AS

Reputation: 161

Just add top, leading, trailing constraints to the custom view with respect to its superview. Add the bottom constraint to the top another view that will lie below your custom view & is also a subview on your custom view's superview.

In your code the problem is with your bottom constraint as well. You are trying to add the constraint b/w the bottom of custom view & top of navigation bar.

 let topConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.top, multiplier: 1, constant: 0)

let leadingConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.leading, multiplier: 1, constant: 0)

let trailingConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.trailing, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.trailing, multiplier: 1, constant: 0)

let bottomConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: anotherView, attribute: NSLayoutAttribute.top, multiplier: 1, constant: 0)

Upvotes: 1

Related Questions