Limitations in the code using swift - cannot be activated

I am trying to understand the limitations of auto-detection. Following the Ray W task (no solution or discussion), the layout should look like this:

desired layout

The implementation of this in IB was quite simple - to create a yellow view with a width and height, vertically centered and horizontally fixed in the fields; then create labels, fields, and a button with simple restrictions inside this view.

My first question is: if the labels have their own content size and everything else is tied to the yellow view, then why do I need to define a fixed width and height? Why doesn't he infer the width and height from the inner contents of his subzones?

Moving and trying to recreate this layout in code gave me an error:

Application termination due to an undetected "NSGenericException" exception, Reason: "Unable to activate the restriction using <UILabel: 0x7a961d60; frame = (0 0; 0 0); text = 'Password:'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7a961e40>> and <UIView: 0x7a96b6f0; frame = (0 0; 0 0); layer = <CALayer: 0x7a96b880>> because they don’t have a common ancestor. Does the reference position have restrictions in different view hierarchies? Is it illegal " .

The second question: what are these layers, and all my views are in heirachy - superview contains a yellow view containing text labels and fields.

After a lot of pain, I tried to accurately recreate the restrictions made in IB, but this only added the following error: It is impossible to satisfy the restrictions at the same time.

 ( "<NSLayoutConstraint:0x7ac57370 H:[UIView:0x7a96b6f0(0)]>", "<NSLayoutConstraint:0x7ac57400 H:|-(8)-[UILabel:0x7a96bb50'Username:'] (Names: '|':UIView:0x7a96b6f0 )>", "<NSLayoutConstraint:0x7ac57430 UILabel:0x7a96bb50'Username:'.trailing == UITextField:0x7a961020.leading + 8>", "<NSLayoutConstraint:0x7ac57520 UITextField:0x7a961020.trailing == UIView:0x7a96b6f0.trailing - 8>" ) 

Final question (s): How do I know what a 0x7aetc view is? And where is the restriction in my code? The rest looks fine (?).

I have to do something very wrong at some basic level.

Here is my code:

 import UIKit class ViewController: UIViewController { let centerView = UIView() let usernameLabel = UILabel() let passwordLabel = UILabel() let usernameField = UITextField() let passwordField = UITextField() let submitButton = UIButton() override func viewDidLoad() { super.viewDidLoad() centerView.backgroundColor = UIColor.yellowColor() usernameLabel.text = "Username:" passwordLabel.text = "Password:" usernameField.borderStyle = .RoundedRect passwordField.borderStyle = .RoundedRect submitButton.setTitle("Submit!", forState: .Normal) submitButton.setTitleColor(UIColor.blackColor(), forState: .Normal) submitButton.setTitleColor(UIColor.blueColor(), forState: .Highlighted) view.addSubview(centerView) self.centerView.addSubview(usernameField) self.centerView.addSubview(passwordField) self.centerView.addSubview(usernameLabel) self.centerView.addSubview(submitButton) let constraintCenterViewHeight = NSLayoutConstraint(item: centerView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 0) let constraintCenterViewWidth = NSLayoutConstraint(item: centerView, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 0) let constraintCenterViewCenterX = NSLayoutConstraint(item: centerView, attribute: .CenterX, relatedBy: .Equal, toItem: view, attribute: .CenterX, multiplier: 1.0, constant: 0) let constraintCenterViewCenterY = NSLayoutConstraint(item: centerView, attribute: .CenterY, relatedBy: .Equal, toItem: view, attribute: .CenterY, multiplier: 1.0, constant: 0) let constraintUsernameLabelHLeading = NSLayoutConstraint(item: usernameLabel, attribute: .Leading, relatedBy: .Equal, toItem: centerView, attribute: .Leading, multiplier: 1.0, constant: 8) let constraintUsernameLabelHTrailing = NSLayoutConstraint(item: usernameLabel, attribute: .Trailing, relatedBy: .Equal, toItem: usernameField, attribute: .Leading, multiplier: 1.0, constant: 8) let constraintUsernameLabelAlignBottom = NSLayoutConstraint(item: usernameLabel, attribute: .Bottom, relatedBy: .Equal, toItem: usernameField, attribute: .Bottom, multiplier: 1.0, constant: 0) let constraintUsernameFieldVTop = NSLayoutConstraint(item: usernameField, attribute: .Top, relatedBy: .Equal, toItem: centerView, attribute: .Top, multiplier: 1.0, constant: 8) let constraintUsernameFieldHTrailing = NSLayoutConstraint(item: usernameField, attribute: .Trailing, relatedBy: .Equal, toItem: centerView, attribute: .Trailing, multiplier: 1.0, constant: -8) let constraintUsernameFieldVBottom = NSLayoutConstraint(item: usernameField, attribute: .Bottom, relatedBy: .Equal, toItem: passwordField, attribute: .Top, multiplier: 1.0, constant: 8) let constraintPasswordLabelHLeading = NSLayoutConstraint(item: passwordLabel, attribute: .Leading, relatedBy: .Equal, toItem: centerView, attribute: .Leading, multiplier: 1.0, constant: 8) let constraintPasswordLabelHTrailing = NSLayoutConstraint(item: passwordLabel, attribute: .Trailing, relatedBy: .Equal, toItem: passwordField, attribute: .Leading, multiplier: 1.0, constant: 8) let constraintPasswordLabelAlignBottom = NSLayoutConstraint(item: passwordLabel, attribute: .Bottom, relatedBy: .Equal, toItem: passwordField, attribute: .Bottom, multiplier: 1.0, constant: 0) let constraintPasswordFieldHTrailing = NSLayoutConstraint(item: passwordField, attribute: .Trailing, relatedBy: .Equal, toItem: centerView, attribute: .Trailing, multiplier: 1.0, constant: -8) centerView.setTranslatesAutoresizingMaskIntoConstraints(false) usernameLabel.setTranslatesAutoresizingMaskIntoConstraints(false) usernameField.setTranslatesAutoresizingMaskIntoConstraints(false) passwordField.setTranslatesAutoresizingMaskIntoConstraints(false) passwordLabel.setTranslatesAutoresizingMaskIntoConstraints(false) // submitButton.setTranslatesAutoresizingMaskIntoConstraints(false) NSLayoutConstraint.activateConstraints([constraintCenterViewHeight, constraintCenterViewWidth, constraintCenterViewCenterX, constraintCenterViewCenterY, constraintUsernameLabelHLeading, constraintUsernameLabelHTrailing, constraintUsernameLabelAlignBottom, constraintUsernameFieldVTop, constraintUsernameFieldHTrailing, constraintUsernameFieldVBottom, constraintPasswordLabelHLeading, constraintPasswordLabelHTrailing, constraintPasswordLabelAlignBottom, constraintPasswordFieldHTrailing]) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } } 
+6
source share
2 answers

My first question is: if labels have their own size for the content and everything else is tied to yellow, then why do I need to define a fixed width and height? Why not give him the width and height of the inner contents of his subzones?

The username and password fields have no width. They get the width by attaching them to the labels on the left and right edges of the centerView . If you add constraints to give these fields a width, then centerView can determine its width from its content.


Moving and trying to recreate this layout in the code gave me Error: the application terminated due to the unselected "NSGenericException" exception, Reason: "It is not possible to activate the restriction with the> and> elements because they do not have a common ancestor. Are there restriction reference positions in different hierarchy of representations? This is illegal.

Your first problem is that you did not add passwordLabel as a subtitle:

 self.centerView.addSubview(passwordLabel) 

This is what gave you the error. passwordLabel not in the view hierarchy, so Auto Layout did not know how to limit it using centerView .

The second problem is that you set the width and height in the centerView to 0 . Try larger values, like 100 and 300 :

 let constraintCenterViewHeight = NSLayoutConstraint(item: centerView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 100) let constraintCenterViewWidth = NSLayoutConstraint(item: centerView, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 300) 

Your third problem is that some of your constants should be negative:

 // changed to -8 let constraintUsernameLabelHTrailing = NSLayoutConstraint(item: usernameLabel, attribute: .Trailing, relatedBy: .Equal, toItem: usernameField, attribute: .Leading, multiplier: 1.0, constant: -8) // changed to -8 let constraintUsernameFieldVBottom = NSLayoutConstraint(item: usernameField, attribute: .Bottom, relatedBy: .Equal, toItem: passwordField, attribute: .Top, multiplier: 1.0, constant: -8) // changed to -8 let constraintPasswordLabelHTrailing = NSLayoutConstraint(item: passwordLabel, attribute: .Trailing, relatedBy: .Equal, toItem: passwordField, attribute: .Leading, multiplier: 1.0, constant: -8) 
+15
source

I got the same error, but the reason this happened was something else:

I got an error because I referred to my supervisor before . I added a view to his supervisor. <- writing your code as such is no different from what view.addSubview(stackView) does not include. Both will generate the same error, because the view has no specific relation to its supervision.

In my code below, lines B1, B2 occur before I add the view to the supervisor (on line AA).

This is my code:

 class ViewController: UIViewController { var label = UILabel() var button = UIButton() var stackView = UIStackView() override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = UIColor.cyan navigationItem.title = "VCTitle" setupUI() } private func setupUI(){ label.backgroundColor = UIColor.blue label.heightAnchor.constraint(equalToConstant: 50).isActive = true label.widthAnchor.constraint(equalToConstant: 80).isActive = true button.backgroundColor = UIColor.purple button.heightAnchor.constraint(equalToConstant: 30).isActive = true button.widthAnchor.constraint(equalToConstant: 10).isActive = true setupStackView() stackView.addArrangedSubview(label) stackView.addArrangedSubview(button) stackView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(stackView) // AA } private func setupStackView(){ stackView.axis = UILayoutConstraintAxis.vertical stackView.distribution = UIStackViewDistribution.equalSpacing stackView.alignment = UIStackViewAlignment.center stackView.spacing = 15 stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true // B1 stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true // B2 } } 

The correct way to do this is to move line B1, B2 to any point after line AA.

 class ViewController: UIViewController { var label = UILabel() var button = UIButton() var stackView = UIStackView() override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = UIColor.cyan navigationItem.title = "VCTitle" setupUI() } private func setupUI(){ label.backgroundColor = UIColor.blue label.heightAnchor.constraint(equalToConstant: 50).isActive = true label.widthAnchor.constraint(equalToConstant: 80).isActive = true button.backgroundColor = UIColor.purple button.heightAnchor.constraint(equalToConstant: 30).isActive = true button.widthAnchor.constraint(equalToConstant: 10).isActive = true setupStackView() stackView.addArrangedSubview(label) stackView.addArrangedSubview(button) stackView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(stackView) //AA // The 2 lines below are now in the right place. stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true // B1 stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true // B2 } private func setupStackView(){ stackView.axis = UILayoutConstraintAxis.vertical stackView.distribution = UIStackViewDistribution.equalSpacing stackView.alignment = UIStackViewAlignment.center stackView.spacing = 15 } } 
+4
source

All Articles