13

I am trying to add constraints to a facebook sdk login button.

I have the button inside a scroll view and I am trying to add a top constraint to a label that is also in the scroll view. I am able to successfully add the height constraint with no run time errors but the actual constraint does not seem to be applied to the button.

@IBOutlet weak var orLbl: UILabel!
@IBOutlet weak var scrollView: UIScrollView!

override func viewDidLoad() {
    super.viewDidLoad()
    var loginFBButton = FBSDKLoginButton()
    loginFBButton.readPermissions = ["public_profile", "email"]

    let heightConstraint = NSLayoutConstraint(
        item: loginFBButton,
        attribute: NSLayoutAttribute.Height,
        relatedBy: NSLayoutRelation.Equal,
        toItem: nil,
        attribute: NSLayoutAttribute.NotAnAttribute,
        multiplier: 1,
        constant: 41)
    let topConstraint = NSLayoutConstraint(
        item: loginFBButton,
        attribute: NSLayoutAttribute.TopMargin,
        relatedBy: NSLayoutRelation.Equal,
        toItem: self.orLbl,
        attribute: NSLayoutAttribute.BottomMargin,
        multiplier: 1,
        constant: 31)
    let leadingConstraint = NSLayoutConstraint(
        item: loginFBButton,
        attribute: NSLayoutAttribute.Leading,
        relatedBy: NSLayoutRelation.Equal,
        toItem: self.registerButton,
        attribute: NSLayoutAttribute.Left,
        multiplier: 1,
        constant: 0)
    let trailingConstraint = NSLayoutConstraint(
        item: loginFBButton,
        attribute: NSLayoutAttribute.Leading,
        relatedBy: NSLayoutRelation.Equal,
        toItem: self.registerButton,
        attribute: NSLayoutAttribute.Right,
        multiplier: 1,
        constant: 0)

    self.scrollView.addSubview(loginFBButton)
    //loginFBButton.center = self.scrollView.center

    loginFBButton.addConstraints([heightConstraint, topConstraint])

}

Then when I include the addition of the top constraint, I am getting a runtime 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.

Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to install constraint on view. Does the constraint reference something from outside the subtree of the view? That's illegal.

Both the label and the facebook button are in my scroll view? I've even printed out orLbl.superview and loginFBButton.superview and I am getting optional uiscrollview for both

2
  • Have you tried to figure out, which of the two constraints causes the exception? Commented Jul 7, 2015 at 9:53
  • @freytag yes as mentioned in the question, it was when I added the top constraint, the crash was happening. Another user suggested to add the constraints to the scrollview instead of the loginFBButton. I did that and got no runtime errors but then my facebook button is up at the top left of the screen and the or label is completely off screen Commented Jul 7, 2015 at 10:30

1 Answer 1

29

There is a new (iOS8, OS 10.10), easier way to activate constraints that doesn't involve figuring out which views to add them to. The constraints already know which views they belong to, so first make sure your views have been added as subViews, then call the class method activateConstraints on NSLayoutConstraint to activate them:

 NSLayoutConstraint.activateConstraints([heightConstraint, topConstraint])

When you create UI elements programmatically, you need to tell iOS not to turn its frame into constraints. To do that, just after creating loginFBButton do:

For Swift 1.2:

loginFBButton.setTranslatesAutoresizingMaskIntoConstraints(false)

For Swift 2.0 & 3.0:

loginFBButton.translatesAutoresizingMaskIntoConstraints = false

Finally, you are going to need more constraints. I suggest setting a width constraint for your loginFBButton and adding a constraint to position the button horizontally.

Sign up to request clarification or add additional context in comments.

4 Comments

I have updated the code to include all of the constraints i was using. So at this point am i still adding constraints and then setting the translateAutoresizingMaskIntoConstraints bool or what is the flow?
Create your button, set translatesAutoresizingMaskIntoConstraints to false, add your button to the scrollView, create the constraints and active them.
thank you I got it to work using, loginFBButton.setTranslatesAutoresizingMaskIntoConstraints(false). I also had to make sure to add the constraints to the scroll view and not the loginFBButton. I did not have to use the activate constraints however
Yes, the activate constraints is not required, its just a lot easier than figuring out which views to add the constraints to.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.