atahualpapena
atahualpapena

Reputation: 11

Error trying to set the constraints for a UIButton

Error:

2018-05-13 01:32:25.577503-0400 LoginScreen[2606:70991] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to activate constraint with anchors <NSLayoutYAxisAnchor:0x60000046acc0 "UIButton:0x7fb4cad0b120'Forgot Password?'.top"> and <NSLayoutYAxisAnchor:0x60000046ad40 "UIButton:0x7fb4cad0a160'Log In'.bottom"> because they have no common ancestor. Does the constraint or its anchors reference items in different view hierarchies? That's illegal.'

Source Code:

import UIKit

class ViewController: UIViewController {


    let emailTextField: UITextField = {
        let e = UITextField()

        let attributedPlaceHolder = NSAttributedString(string: "Email", attributes:
            [NSAttributedStringKey.foregroundColor: UIColor.white])
        e.attributedPlaceholder = attributedPlaceHolder
        e.backgroundColor = GREEN_THEME

        return e
    }()

    let passwordTextField: UITextField = {
        let p = UITextField()
        let attributedPlaceHolder = NSAttributedString(string: "Password", attributes:
            [NSAttributedStringKey.foregroundColor: UIColor.white])
        p.attributedPlaceholder = attributedPlaceHolder
        p.backgroundColor = GREEN_THEME
        return p
    }()

    let loginButton: UIButton = {
        let l = UIButton(type: .system)
        l.setTitleColor( .white, for: .normal)
        l.setTitle("Log In", for: .normal)
        l.backgroundColor = GREEN_THEME
        return l
    }()

    let forgotPasswordButton: UIButton = {
        let f = UIButton(type: .system)
        f.setTitleColor( .white, for: .normal)
        f.setTitle("Forgot Password?", for: .normal)
        f.backgroundColor = GREEN_THEME
        return f
    }()

    let haveAccountButton: UIButton = {
        let color = UIColor(red: 89/255, green: 156/255, blue: 120/255, alpha: 1 )
        let font = UIFont.systemFont(ofSize: 16)
        let h = UIButton(type: .system)
            h.backgroundColor = GREEN_THEME
        let attributedTitle = NSMutableAttributedString(string:
            "Don't have an accoun?", attributes:
            [NSAttributedStringKey.foregroundColor: color, NSAttributedStringKey.font: font ])

            attributedTitle.append(NSAttributedString(string: "Sign Up", attributes: [NSAttributedStringKey.foregroundColor: UIColor.white,
                                                                                  NSAttributedStringKey.font: font ]))

        h.setAttributedTitle(attributedTitle, for: .normal)
        return h
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = GREEN_THEME

        setupTextFieldComponents()
        setupLoginButton()
    } 

    fileprivate func setupTextFieldComponents(){

        setupEmailField()
        setupPasswordField()
        setupHaveAccountButton()
        setupForgotPasswordButton()

    }

    override var preferredStatusBarStyle: UIStatusBarStyle{

        return .lightContent
    }


    fileprivate func setupEmailField(){
        view.addSubview(emailTextField)

        emailTextField.translatesAutoresizingMaskIntoConstraints = false

        emailTextField.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 16).isActive = true
        emailTextField.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 24).isActive = true
        emailTextField.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -24).isActive = true
        emailTextField.heightAnchor.constraint(equalToConstant: 30).isActive = true
        emailTextField.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    }


    fileprivate func setupPasswordField(){
        view.addSubview(passwordTextField)

        passwordTextField.translatesAutoresizingMaskIntoConstraints = false

        passwordTextField.topAnchor.constraint(equalTo: emailTextField.bottomAnchor, constant: 8).isActive = true
        passwordTextField.leftAnchor.constraint(equalTo: emailTextField.leftAnchor, constant: 0).isActive = true
        passwordTextField.rightAnchor.constraint(equalTo: emailTextField.rightAnchor, constant: 0).isActive = true
        passwordTextField.heightAnchor.constraint(equalToConstant: 30).isActive = true
    }


    fileprivate func setupLoginButton(){
        view.addSubview(loginButton)

        loginButton.translatesAutoresizingMaskIntoConstraints = false

        loginButton.topAnchor.constraint(equalTo: passwordTextField.bottomAnchor, constant: 8).isActive = true
        loginButton.leftAnchor.constraint(equalTo: passwordTextField.leftAnchor, constant: 0).isActive = true
        loginButton.rightAnchor.constraint(equalTo: passwordTextField.rightAnchor, constant: 0).isActive = true
        loginButton.heightAnchor.constraint(equalToConstant: 30).isActive = true
    }

  fileprivate func setupForgotPasswordButton(){
        view.addSubview(forgotPasswordButton)


        forgotPasswordButton.translatesAutoresizingMaskIntoConstraints = false

        forgotPasswordButton.topAnchor.constraint(equalTo: loginButton.bottomAnchor, constant: 8).isActive = true
        forgotPasswordButton.leftAnchor.constraint(equalTo: loginButton.leftAnchor, constant: 0).isActive = true
        forgotPasswordButton.rightAnchor.constraint(equalTo: loginButton.rightAnchor, constant: 0).isActive = true
        forgotPasswordButton.heightAnchor.constraint(equalToConstant: 30).isActive = true
    }

    fileprivate func setupHaveAccountButton(){
        view.addSubview(haveAccountButton)

        haveAccountButton.translatesAutoresizingMaskIntoConstraints = false

        haveAccountButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -8).isActive = true
        haveAccountButton.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 12).isActive = true
        haveAccountButton.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -12).isActive = true
        haveAccountButton.heightAnchor.constraint(equalToConstant: 30).isActive = true
    }
}

Upvotes: 1

Views: 183

Answers (1)

Abish Dangol
Abish Dangol

Reputation: 60

First, you should add both forgotPasswordButton and loginButton as subView to your view

view.addSubview(forgotPasswordButton)
view.addSubview(loginButton)

Then, the constraints should work.

Upvotes: 1

Related Questions