Dhruv Upadhyay
Dhruv Upadhyay

Reputation: 151

"The view hierarchy is not prepared for the constraint" error Swift 3

I'm trying to add a button and set the constraints programmatically, but I keep getting this error and can't figure out what's wrong with my code. I've looked at other questions on here but they haven't been too helpful in my case.

    btn.setTitle("mybtn", for: .normal)
    btn.setTitleColor(UIColor.blue, for: .normal)
    btn.backgroundColor = UIColor.lightGray
    view.addSubview(btn)
    btn.translatesAutoresizingMaskIntoConstraints = false

    let left = NSLayoutConstraint(item: btn, attribute: .leftMargin, relatedBy: .equal, toItem: view, attribute: .leftMargin, multiplier: 1.0, constant: 0)

    let right = NSLayoutConstraint(item: btn, attribute: .rightMargin, relatedBy: .equal, toItem: view, attribute: .rightMargin, multiplier: 1.0, constant: 0)

    let top = NSLayoutConstraint(item: btn, attribute: .top, relatedBy: .equal, toItem: topLayoutGuide, attribute: .bottom, multiplier: 1.0, constant: 0)

    btn.addConstraints([left, right, top])

Upvotes: 8

Views: 4597

Answers (3)

Paulo Mattos
Paulo Mattos

Reputation: 19339

Try adding left and rightconstraints to the view instead of btn.

Upvotes: 0

Rob
Rob

Reputation: 437882

When adding constraints to a view, "any views involved [in the constraint] must be either the receiving view itself, or a subview of the receiving view". You're adding the constraint to btn, so it doesn't understand what to make of the view referenced by the constraint, because it's neither btn nor a subview of btn. The error would be resolved if you added the constraints to view, instead of btn.

Or even better, as Khalid said, use activate instead, in which case you don't need to worry about where in the view hierarchy you are adding the constraint:

let btn = UIButton(type: .system)
btn.setTitle("mybtn", for: .normal)
btn.setTitleColor(.blue, for: .normal)
btn.backgroundColor = .lightGray
view.addSubview(btn)
btn.translatesAutoresizingMaskIntoConstraints = false

NSLayoutConstraint.activate([
    btn.leftAnchor.constraint(equalTo: view.leftAnchor),
    btn.rightAnchor.constraint(equalTo: view.rightAnchor),
    btn.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor)
])

Upvotes: 19

Khalid Afridi
Khalid Afridi

Reputation: 923

Use activate constraint. as off iOS 9 you can use activate

 btn.setTitle("mybtn", for: .normal)
 btn.setTitleColor(UIColor.blue, for: .normal)
 btn.backgroundColor = UIColor.gray

 btn.translatesAutoresizingMaskIntoConstraints = false
 self.view.addSubview(btn)


let left = NSLayoutConstraint(item: btn, attribute: .leftMargin, relatedBy: .equal, toItem: view, attribute: .leftMargin, multiplier: 1.0, constant: 0)

let right = NSLayoutConstraint(item: btn, attribute: .rightMargin, relatedBy: .equal, toItem: view, attribute: .rightMargin, multiplier: 1.0, constant: 0)

let top = NSLayoutConstraint(item: btn, attribute: .top, relatedBy: .equal, toItem: topLayoutGuide, attribute: .bottom, multiplier: 1.0, constant: 0)

// here you have to call activate constraints everything will work     
NSLayoutConstraint.activate([left, right, top])

example project

Upvotes: 3

Related Questions