Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"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])
like image 596
Dhruv Upadhyay Avatar asked Apr 16 '17 11:04

Dhruv Upadhyay


2 Answers

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)
])
like image 106
Rob Avatar answered Nov 09 '22 23:11

Rob


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

like image 29
Khalid Afridi Avatar answered Nov 09 '22 23:11

Khalid Afridi