Search code examples
iosswiftuiviewautolayoutconstraints

Adding Constraints to ViewController with Swift


I want to add container view to the main view (rootViewController.view), but the following gives exception. I know it about the constraints but not able to find out why.

import UIKit

class rootViewController : UIViewController {

    init() {
        super.init(nibName: nil, bundle: nil)
        setupLoginView()
    }

    func setupLoginView() {

        // User ID label
        let userIDLabel:UILabel = UILabel()
        userIDLabel.text = "User ID"

        // Password label
        let passwordLabel:UILabel = UILabel()
        passwordLabel.text = "Password"

        // User ID text
        let userIDText:UITextField = UITextField()

        // Password text
        let passwordText:UITextField = UITextField()

        // Login button
        let loginBtn:UIButton = UIButton()
        loginBtn.setTitle("Login", for: .normal)

        // Container view
        let container:UIView = UIView()

        container.addSubview(userIDLabel)
        container.addSubview(userIDText)
        container.addSubview(passwordLabel)
        container.addSubview(passwordText)
        container.addSubview(loginBtn)

        view.addSubview(container)

        // Add constraints
        let heightConstraint = NSLayoutConstraint(item: container, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 300)
        let widthConstraint = NSLayoutConstraint(item: container, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 200)
        let centerXConstraint = NSLayoutConstraint(item: container, attribute: .centerX, relatedBy: .equal, toItem: view, attribute: .centerX, multiplier: 1, constant: 0)
        let centerYConstraint = NSLayoutConstraint(item: container, attribute: .centerY, relatedBy: .equal, toItem: view, attribute: .centerY, multiplier: 1, constant: 0)

        container.addConstraint(heightConstraint)
        container.addConstraint(widthConstraint)
        container.addConstraint(centerXConstraint)
        container.addConstraint(centerYConstraint)

    }

}

Gives the following exception, with hint "Does the constraint reference something from outside the subtree of the view? That's illegal"

'NSGenericException', reason: 'Unable to install constraint on view. Does the constraint reference something from outside the subtree of the view? That's illegal. constraint: NSLayoutConstraint:0x170089830 UIView:0x12de138c0.centerX == UIView:0x12de0e650.centerX (active)>


Solution

  • Replace your code for adding the center constraints with these lines:

    view.addConstraint(centerXConstraint)
    view.addConstraint(centerYConstraint)
    

    You can't add a constaint on the container with a reference to it's superview.

    And move the setupLoginView() to viewDidLoad instead of init().

    Don't forget to remove the warning in the console to set translatesAutoresizingMaskIntoConstraints to false for all the created views (container, labels, buttons and textviews).