Tunds
Tunds

Reputation: 1817

NSLayout Constraints failing

So i'm trying to programatically add constraints to my view using the following code. I'm trying to add some top space of 32 and some leading space of 16 to a view which is being added programatically to one of my view controllers but i seems to be running into some issues.

Below is the example of how i'm returning the button to my view so it can be added programatically.

// Creating the button
func createDismissButton(vwParentView: OnboardingViewController) -> UIButton {

     let dismissButton = UIButton()
     dismissButton.setImage(UIImage(named: "Close"), forState: .Normal)
     dismissButton.frame =  CGRectMake(16, 32, 34, 34)
     dismissButton.addTarget(self, action: "dismiss:", forControlEvents: .TouchUpInside)

     // AUTO LAYOUT

    // WIDTH & HEIGHT
    let dismissWidthButtonConstraint = NSLayoutConstraint (item: dismissButton,
        attribute: NSLayoutAttribute.Width,
        relatedBy: NSLayoutRelation.Equal,
        toItem: nil,
        attribute: NSLayoutAttribute.NotAnAttribute,
        multiplier: 1,
        constant: 34)

    let dismissHeightButtonConstraint = NSLayoutConstraint (item: dismissButton,
        attribute: NSLayoutAttribute.Width,
        relatedBy: NSLayoutRelation.Equal,
        toItem: nil,
        attribute: NSLayoutAttribute.NotAnAttribute,
        multiplier: 1,
        constant: 34)

    // SPACING
    let dismissButtonTopConstraint = NSLayoutConstraint(item: dismissButton,
        attribute: .Top,
        relatedBy: .Equal,
        toItem: vwParentView.view,
        attribute: .Top,
        multiplier: 1.0,
        constant: 32)

    let dismissButtonLeftConstraint = NSLayoutConstraint(item: dismissButton,
        attribute: .Leading,
        relatedBy: .Equal,
        toItem: vwParentView.view,
        attribute: .Leading,
        multiplier: 1.0,
        constant: 16)


    dismissButton.addConstraint(dismissWidthButtonConstraint)
    dismissButton.addConstraint(dismissHeightButtonConstraint)

    dismissButton.addConstraint(dismissButtonTopConstraint)
    dismissButton.addConstraint(dismissButtonLeftConstraint)

     return dismissButton
}

But it seems to be failing on the spacing i add vwParentView.viewsince it was bring up an error in the log about the item property having to be a view. But now when i run the code with the these properties i'm getting the following error.

'NSInternalInconsistencyException', reason: 'Impossible to set up layout with view hierarchy unprepared for constraint.'

I'm trying to add this button to a view which has also been created programatically like so below.

override func viewWillAppear(animated: Bool) {
    // Add the view below to the current view controller
    self.view.addSubview(generatePurchasePaging().view)
}

func generatePurchasePaging() -> OnboardingViewController {

    let welcomePage = OnboardingContentViewController(title: "PAY WHAT YOU WANT", body: "I made my app so you could have the best experience reading tech related news. That’s why I want you to value it based on your satisfaction.", image: UIImage(named: "Purchase-Pig"), buttonText: "") { () -> Void in

    }

    let firstPurchasePage = OnboardingContentViewController(title: "MINT", body: "The app is great but there’s still a few places in room of improvement. If this is your feeling this is for you.", image: UIImage(named: "Purchase-Mint"), buttonText: "69p") { () -> Void in

    }

    let secondPurchasePage = OnboardingContentViewController(title: "SWEET", body: "IThis is the suggested price where you value the time I spent on development and design. Feel free to pay more or less.", image: UIImage(named: "Purchase-Lolly"), buttonText: "£1.49") { () -> Void in

    }

    let thirdPurchasePage = OnboardingContentViewController(title: "GOLD", body: "Hello is it me your looking for, if this popped into your mind using the app then this is the price for you.", image: UIImage(named: "Purchase-Coin"), buttonText: "£2.99") { () -> Void in

    }

    let purchaseVC = OnboardingViewController(backgroundImage: nil, contents: [welcomePage, firstPurchasePage, secondPurchasePage, thirdPurchasePage])
   purchaseVC.shouldMaskBackground = false

    purchaseVC.view.addSubview(createDismissButton(purchaseVC))
    return purchaseVC
}

Upvotes: 2

Views: 118

Answers (1)

Rob
Rob

Reputation: 438297

A few thoughts:

  1. When you programmatically create a view, translatesAutoresizingMaskIntoConstraints defaults to true. Turn this off.

  2. You are setting constraints to another view (its superview?) before adding it to the view hierarchy. So make sure (a) you first perform addSubiew and (b) this constraint should be added to the nearest common parent (usually the superview), not to the button, itself. The .NotAnAttribute constraints can be added to the button, but the rest should be added to the nearest common parent.

  3. You are setting both the constraints and the frame. If you do the former, the latter is not needed.

If it's still not working after you remedy the above, please share the full text of the error, not just the one-line message.

Upvotes: 3

Related Questions