1

I am going through Big Nerd Ranch, iOS textbook's 16 chapter and trying to add constraints programmatically (Xcode 7.1, iOS) but it results in the following error:

The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x7f96f1e272a0 H:|-(0)-[UIImageView:0x7f96f1e3ba90]   
(Names: '|':UIControl:0x7f96f1e33550 )>
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. 
Break on -[UIView(UIConstraintBasedLayout) _viewHierarchyUnpreparedForConstraint:] to debug.`

There is BNRDetailViewController.xib file that is the view of BNRDetailViewController. Here is the code I am trying to use inside BNRDetailViewController:

- (void)viewDidLoad
{
[super viewDidLoad];

UIImageView *iv = [[UIImageView alloc] initWithImage:nil];

// The contentMode of the image view in the XIB was aspect fit
iv.contentMode = UIViewContentModeScaleAspectFit;

// Do not produce a translated constraint for this view
iv.translatesAutoresizingMaskIntoConstraints = NO;

// The image view was a subview of the view
[self.view addSubview:iv];

// The image view was pointed to by the imageView property
self.imageView = iv;

NSDictionary *nameMap = @{@"imageView": self.imageView,
                          @"dateLabel": self.dateLabel,
                          @"toolbar": self.toolbar};

// imageView is 0 pts from superview at left and right edges
NSArray *horizontalConstraints =
[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[imageView]-0-|" options:0 metrics:nil views:nameMap];

// imageView is 8 pts from dateLabel at its top edge
// and 8 pts from toolbar at its bottom edge
NSArray *verticalConstraints =
[NSLayoutConstraint constraintsWithVisualFormat:@"V:[dateLabel]-[imageView]-[toolbar]" options:0 metrics:nil views:nameMap];

[self.view addConstraints:horizontalConstraints];
[self.view addConstraints:verticalConstraints];
}
rmaddy
  • 314,917
  • 42
  • 532
  • 579
Nikita Vlasenko
  • 4,004
  • 7
  • 47
  • 87

2 Answers2

0

Your code for creating and applying the constraints, as written, seems fine (and it worked when I tried it in a project of my own). So your problem must be elsewhere. Try running in the debugger, and comparing the addresses given in the error message to the addresses of self.imageView and self.view. Maybe one of those isn't set properly.

In particular, the error says that "|" (the superview is mapping to a uiControl. That's not necessarily a problem, but looks a little fishy. I'd normally expect that you'd be adding a subview to a UIView, rather than a control.

Mark Bessey
  • 19,598
  • 4
  • 47
  • 69
  • The `view`, I mean, the main frame in the .xib file that represents the borders of an iPhone, is set to `UIControl` in Identity Inspector, Custom Class. I need it to be able to dismiss keyboard by touching the background (there are some text fields present in the frame). – Nikita Vlasenko Nov 13 '15 at 22:59
  • Changing from `UIControl` to `UIView` does not help – Nikita Vlasenko Nov 13 '15 at 23:15
  • I just looked over their (Big Nerd Ranch, iOS textbook) code and it is the same for `viewDidLoad` and it is somehow working for them. The immediate difference that I can see is that in their .xib I can not select the size of the view (like wCompact, hAny) right above the console, but in my .xib I can and it is actually a source of problems, since setting up the size making it not working for the other size (which is my other question, not that related to the current one: http://stackoverflow.com/questions/33662924/ios-change-size-of-xib-view-to-wany-hany-xcode-7-1). – Nikita Vlasenko Nov 13 '15 at 23:45
0

OK, I found the problem which also answers my other unanswered question (https://stackoverflow.com/questions/33662924/ios-change-size-of-xib-view-to-wany-hany-xcode-7-1). In the File Inspector, Interface Builder Document I had both options selected: Use Auto Layout and Use Size Classes. By default, when we create a new .xib in Xcode 7, both options are selected. Unchecking Use Size Classes solves the issue of the current question, the program is not crashing anymore. It also solves the other question letting me successfully run the app on different simulators without views disappearing.

Although the problem is solved, I ran across another one: Developing universal in Xcode 6 So, if, say, I want to have a universal app, and specify different settings for iPhone vs iPad I still do not know how to do this. And if you follow what they propose in the question linked (they select both options), you can potentially run into issues with Xcode 7 the way I did. Maybe the only solution I can think of is to try to override supportedInterfaceOrientations method of UIViewControllers, and others, to change the behavior depending on the device. However, a plenty of methods before iOS9 that could be used to control orientation (for example, statusBarOrientation) were deprecated and Apple now recommends to use Use Size Classes option...

Community
  • 1
  • 1
Nikita Vlasenko
  • 4,004
  • 7
  • 47
  • 87