2

I can't figure out how to fix this: I want to create a match game, where the size of the cards depends on the device.

I thought I would create a contentView which I pinned to top and bottom of the rootView with a margin of 20 and alligned it to its center. Then I give it an aspect ratio of 3/4 (for 3 rows and 4 columns).

let contentView = UIView()
// place contentView on the view
self.view.addSubview(contentView)
contentView.translatesAutoresizingMaskIntoConstraints = false

//add position constraints to thecontentView
let topMargin = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 20)
let bottomMargin = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: -20)

let horzontalAllignment = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0)
let verticalAllignment = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0)

self.view.addConstraints([topMargin, bottomMargin, horzontalAllignment, verticalAllignment])

//  create an aspect ratio for the contentView
let aspect = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Height, multiplier: 4/3, constant: 0)
contentView.addConstraint(aspect)

That works perfectly. (Whohoo!) Then I want to create a card that has a quarter of the contentView width and a third of the hight:

let thisCard = Card()
contentView.addSubview(thisCard)
thisCard.translatesAutoresizingMaskIntoConstraints = false

let hightConstraint = NSLayoutConstraint(item: thisCard, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Height, multiplier: 1/3, constant: 0)

let widthConstraint = NSLayoutConstraint(item: thisCard, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Width, multiplier: 1/4, constant: 0)

thisCard.addConstraints([hightConstraint, widthConstraint])

There the code breaks and I get the message:

The view hierarchy is not prepared for the constraint: NSLayoutConstraint:0x78f1b290 Meeres_Memo_temp_caseinsensitive_renamery.Card:0x78f41820.height == UIView:0x78f49fc0.height 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.

Is it even possible, to do want I want to?

Update:

I just found my error. I added the heightConstraint and widthConstraint to thisCard, but they need to be added to the the related view that is higher in the view hierarchy, in this case the contentView, like this:

contentView.addConstraints([hightConstraint, widthConstraint])
1
  • Check out this library, it might help you with constraints programatically. github.com/PureLayout/PureLayout Commented Sep 28, 2015 at 20:35

1 Answer 1

0

Read the error message. You can only add constraints if the items are in the same view hierarchy. I would think that you tried to add the constraints before either thisCard or contentView were added to a view hierarchy. You need to do that first.

BTW. 1/4 is not what you think - it is a big fat zero. 1/4 uses integer division. Use 1.0 / 4, for example.

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

1 Comment

Could you clarify that? I added the contenView as a subview of the rootview and the card as a subview to the contentView (in the code above). Is there something else I need to do?

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.