Search code examples
iosswiftxcodeautolayout

"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])

Solution

  • 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)
    ])