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

  • 0
    いいね
  • 0
    コメント

    起きたこと

    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],