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

# 起きたこと

The view hierarchy is not prepared for the constraintが出たら見るページ
https://qiita.com/naoyashiga/items/0220333f280f69ff889b

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

# コード

```Objective-C
- (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"]]];
    }
}
```
```text
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 をしなければならなかった.

# 修正

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