Posted at

The view hierarchy is not prepared for the constraint の忘れがちなこと

More than 1 year has passed since last update.


起きたこと

The view hierarchy is not prepared for the constraintが出たら見るページ

https://qiita.com/naoyashiga/items/0220333f280f69ff889b

の通りにしても解決しなかった.


コード

- (nonnull NSLayoutConstraint *)constraintTo:(nullable id)view

attribute:(NSLayoutAttribute)attrTo
myAttribute:(NSLayoutAttribute)attrFrom
{
return [NSLayoutConstraint constraintWithItem:_webView
attribute:attrFrom
relatedBy:NSLayoutRelationEqual
toItem:view
attribute:attrTo
multiplier:1.0f
constant:0.0f];
}

- (void)loadView {
[super loadView];
_webView = [[WKWebView alloc]
initWithFrame:CGRectMake(0.0f, 20.0f, 320.0f, 499.0f)
configuration:[WKWebViewConfiguration new]];
_webView.translatesAutoresizingMaskIntoConstraints = NO;
_webView.contentMode = UIViewContentModeScaleToFill;
_webView.backgroundColor = [UIColor colorWithRed:0.3607843137f
green:0.3882352941f
blue:0.4039215686f
alpha:1.0f];
_webView.allowsBackForwardNavigationGestures = YES;
_webView.UIDelegate = self;
[self.view addSubview:_webView];

}

- (void)viewDidLoad {
[super viewDidLoad];
@autoreleasepool {
[_webView addConstraints:@[
[self constraintTo:self.topLayoutGuide
attribute:NSLayoutAttributeBottom
myAttribute:NSLayoutAttributeTop],
[self constraintTo:self.bottomLayoutGuide
attribute:NSLayoutAttributeTop
myAttribute:NSLayoutAttributeBottom],
[self constraintTo:self.view
attribute:NSLayoutAttributeLeft
myAttribute:NSLayoutAttributeLeft],
[self constraintTo:self.view
attribute:NSLayoutAttributeRight
myAttribute:NSLayoutAttributeRight],
]];
[_webView loadRequest:[
NSURLRequest requestWithURL:[
NSURL URLWithString:@"https://www.google.com"]]];
}
}

2017-10-12 17:27:20.480601 TestProject[3631:193034] [LayoutConstraints] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x600000287030 V:[_UILayoutGuide:0x7fefbfd01a90]-(0)-[WKWebView:0x7fefc084f400]   (inactive)>

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.
2017-10-12 17:27:20.484783 TestProject[3631:193034] [LayoutConstraints] View hierarchy unprepared for constraint.
Constraint: <NSLayoutConstraint:0x600000287030 V:[_UILayoutGuide:0x7fefbfd01a90]-(0)-[WKWebView:0x7fefc084f400] (active)>
Container hierarchy:
<WKWebView: 0x7fefc084f400; frame = (0 20; 320 499); gestureRecognizers = <NSArray: 0x60800004e6d0>; layer = <CALayer: 0x60000022d180>>
| <WKScrollView: 0x7fefc0869a00; baseClass = UIWebScrollView; frame = (0 0; 320 499); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x60000004ce10>; layer = <CALayer: 0x60000022da40>; contentOffset: {0, 0}; contentSize: {0, 0}>
| | <WKContentView: 0x7fefc086c600; frame = (0 0; 320 499); gestureRecognizers = <NSArray: 0x60000004f9f0>; layer = <CALayer: 0x60000022d8e0>>
| | | <UIView: 0x7fefbfc17c00; frame = (0 0; 320 499); clipsToBounds = YES; layer = <CALayer: 0x60800023fa40>>
| | | | <UIView: 0x7fefbfd186c0; frame = (0 0; 320 499); autoresize = W+H; layer = <CALayer: 0x60800023faa0>>
| | <UIView: 0x7fefbfc17da0; frame = (0 0; 0 0); opaque = NO; layer = <CALayer: 0x60800023fb00>>
View not found in container hierarchy: <_UILayoutGuide: 0x7fefbfd01a90; frame = (0 0; 0 0); hidden = YES; layer = <CALayer: 0x60000022d2c0>>
That view's superview: <UIView: 0x7fefbfd051b0; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x60000022d280>>
2017-10-12 17:27:20.495 TestProject[3631:193034] *** 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.


間違っていたところ

Stackoverflow (英語) に書いてあった.

View hierachy not prepared for constraint

https://stackoverflow.com/questions/28529434/view-hierachy-not-prepared-for-constraint


Constraints need to be added to a common ancestor of all involved views (where a view is considered an ancestor of itself for this purpose). self.blurView is a subview of self.view. The constraints involve both self.blurView and self.view. Therefore, the constraints need to be added to self.view, not self.blurView.

By the way, your clue should be this part of the error message (which you didn't quote, but your associated did here):


When added to a view, the constraint's items must be descendants of that view (or the view itself).



https://translate.google.com/#auto/ja/Constraints%20need%20to%20be%20added%20to%20a%20common%20ancestor%20of%20all%20involved%20views%20(where%20a%20view%20is%20considered%20an%20ancestor%20of%20itself%20for%20this%20purpose).%20self.blurView%20is%20a%20subview%20of%20self.view.%20The%20constraints%20involve%20both%20self.blurView%20and%20self.view.%20Therefore%2C%20the%20constraints%20need%20to%20be%20added%20to%20self.view%2C%20not%20self.blurView.%0A%0ABy%20the%20way%2C%20your%20clue%20should%20be%20this%20part%20of%20the%20error%20message%20(which%20you%20didn't%20quote%2C%20but%20your%20associated%20did%20here)%3A%0A%0AWhen%20added%20to%20a%20view%2C%20the%20constraint's%20items%20must%20be%20descendants%20of%20that%20view%20(or%20the%20view%20itself).%20


制約は、関連するすべてのビュー(この目的のためにビューがそれ自体の祖先とみなされる)の共通の祖先に追加する必要があります。 self.blurViewはself.viewのサブビューです。 制約には、self.blurViewとself.viewの両方が含まれます。 したがって、self.blurViewではなくself.viewに制約を追加する必要があります。

ところで、あなたの手がかりはエラーメッセージのこの部分でなければなりません(これはあなたが引用していませんでしたが、あなたの関連はここでした)。


ビューに追加するとき、制約のアイテムはそのビューの子孫(またはビュー自体)でなければなりません。



つまり, サブビューに対して addConstraints してはダメで, 親ビューに対して addConstraints をしなければならなかった.


修正

 - (void)viewDidLoad {

[super viewDidLoad];
@autoreleasepool {
- [_webView addConstraints:@[
+ [self.view addConstraints:@[
[self constraintTo:self.topLayoutGuide
attribute:NSLayoutAttributeBottom
myAttribute:NSLayoutAttributeTop],