Search code examples
iosswiftnslayoutconstraint

App is crashing on NSLayoutConstraint when added programmatically


I am getting the following error :

When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView(UIConstraintBasedLayout)

Basically I want to have a blue view that is 200h x 200w that is centered in the middle of the screen.

UIViewController.swift

override func loadView() {
    super.loadView()
    self.view = View()
}

Meanwhile in the View.swift

class View: UIView {
var blueView : UIView?

convenience init() {
    // also tried  UIScreen.mainScreen().bounds
    self.init(frame:CGRectZero)
    self.backgroundColor = UIColor.redColor()
    self.setupView()
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init:coder")
}

override init(frame: CGRect) {
    super.init(frame: frame)
}

func setupView() {
    self.blueView = UIView()
    self.blueView?.backgroundColor = UIColor.blueColor()
    self.blueView?.translatesAutoresizingMaskIntoConstraints = false
    // self.translatesAutoresizingMaskIntoConstraints = false
    self.addSubview(self.blueView!)

    let centerXConstraint = NSLayoutConstraint(
        // object that we want to constrain
        item: self.blueView!,
        // the attribute of the item we want to constraint
        attribute: NSLayoutAttribute.CenterX,
        // how we want to relate this item with another item so most likely its parent view
        relatedBy: NSLayoutRelation.Equal,
        // this is the item that we are setting up the relationship with
        toItem: self,
        attribute: NSLayoutAttribute.CenterX,
        // How much I want the CenterX of BlueView to Differ from the CenterX of the self
        multiplier: 1.0,
        constant: 0)

    let centerYConstraint = NSLayoutConstraint(
        item: self.blueView!,
        attribute: NSLayoutAttribute.CenterY,
        relatedBy: NSLayoutRelation.Equal,
        toItem: self,
        attribute: NSLayoutAttribute.CenterY,
        multiplier: 1.0,
        constant: 0)

    // These work but the previous two don't
    let widthContraint = NSLayoutConstraint(
        item: self.blueView!,
        attribute: NSLayoutAttribute.Width,
        relatedBy: NSLayoutRelation.Equal,
        toItem: nil, 
        attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0,
        constant: 200)

    let heightConstraint = NSLayoutConstraint(
        item: self.blueView!,
        attribute: NSLayoutAttribute.Height,
        relatedBy: NSLayoutRelation.Equal,
        toItem: nil, 
        attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0,
        constant: 200)

    self.blueView?.addConstraints([widthContraint, heightConstraint, centerXConstraint, centerYConstraint])


}

Solution

  • Height and width constraints belong to the view they pertain to. Centering and positioning belong to that view's parent so you must add these two to the parent, not the view itself.