Autolayout约束和子视图控制器

Ben*_*air 6 objective-c autolayout

我有两个视图控制器,父母和孩子.

所以在viewDidLoad方法中我做了以下几点:

ChildViewController* childViewController = [[ChildViewController alloc] init];

[self addChildViewController:childViewController];

// ChildViewController sets his own constraints in viewDidLoad
[self.view addSubview:childViewController.view];

[childViewController didMoveToParentViewController:self];

//
// setup constraints to expand childViewController.view to 
// fill the size of parent view controller
//
Run Code Online (Sandbox Code Playgroud)

所以基本上会发生什么是updateViewConstraints在父控制器约束应用之前在ChildViewController上调用,所以实际上self.view.frame == CGRectZero,与我在自定义loadView方法中指定的完全相同ChildViewController.

translatesAutoresizingMaskIntoConstraints全部设置NO为所有视图.

在这种情况下设置约束的正确方法是什么,所以ChildViewController在父母之后更新他的约束?

来自两个控制器的当前日志非常令人沮丧,我不明白如何在viewWillLayoutSubviews之前调用updateViewConstraints:

App[47933:c07] ChildViewController::updateViewConstraints. RECT: {{0, 0}, {0, 0}}
App[47933:c07] ParentViewController::updateViewConstraints
App[47933:c07] ChildViewController:viewWillLayoutSubviews. RECT: {{0, 0}, {984, 454}}
App[47933:c07] ChildViewController:viewDidLayoutSubviews. RECT: {{0, 0}, {984, 454}}
Run Code Online (Sandbox Code Playgroud)

Ben*_*itz 7

您可以在调用 addSubview: 后立即添加约束,不要忘记设置translatesAutoresizingMaskIntoConstraintsfalse

这是添加和隐藏带有约束的子视图控制器的代码片段(受苹果指南启发)

展示

private func display(contentController content : UIViewController)
    {
        self.addChildViewController(content)
        content.view.translatesAutoresizingMaskIntoConstraints = false
        self.containerView.addSubview(content.view)
        content.didMove(toParentViewController: self)

        containerView.addConstraints([
            NSLayoutConstraint(item: content.view, attribute: .top, relatedBy: .equal, toItem: containerView, attribute: .top, multiplier: 1, constant: 0),
            NSLayoutConstraint(item: content.view, attribute: .bottom, relatedBy: .equal, toItem: containerView, attribute: .bottom, multiplier: 1, constant: 0),
            NSLayoutConstraint(item: content.view, attribute: .leading, relatedBy: .equal, toItem: containerView, attribute: .leading, multiplier: 1, constant: 0),
            NSLayoutConstraint(item: content.view, attribute: .trailing, relatedBy: .equal, toItem: containerView, attribute: .trailing, multiplier: 1, constant: 0)
            ])
    }
Run Code Online (Sandbox Code Playgroud)

隐藏

private func hide(contentController content : UIViewController)
    {
        content.willMove(toParentViewController: nil)
        content.view.removeFromSuperview()
        content.removeFromParentViewController()
    }
Run Code Online (Sandbox Code Playgroud)


Jon*_*man 5

我有类似的情况,我将子控制器添加到可见控制器(弹出窗口).

我在界面构建器中定义子视图控制器.它的viewDidLoad方法只调用setTranslatesAutoresizingMaskIntoConstraints:NO

然后我在子控制器上定义这个方法,它接受一个UIViewController参数,它是父.此方法将自身添加到给定的父视图控制器并定义其自己的约束:

- (void) addPopupToController:(UIViewController *)parent {
    UIView *view = [self view];
    [self willMoveToParentViewController:parent];
    [parent addChildViewController:self];
    [parent.view addSubview:view];
    [self didMoveToParentViewController:parent];

    NSArray *horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[view]-0-|"
                                                                             options:0
                                                                             metrics:nil
                                                                               views:NSDictionaryOfVariableBindings(view)];
    [parent.view addConstraints:horizontalConstraints];

    NSArray *verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[view]-0-|"
                                                                           options:0
                                                                           metrics:nil
                                                                             views:NSDictionaryOfVariableBindings(view)];
    [parent.view addConstraints:verticalConstraints];
}
Run Code Online (Sandbox Code Playgroud)

然后在父UIViewController(已经显示的那个)里面,当我想显示我调用的子弹出视图控制器时:

PopUpNotificationViewController *popup = [[self storyboard] instantiateViewControllerWithIdentifier:@"NotificationPopup"];
[popup addPopupToController:self];
Run Code Online (Sandbox Code Playgroud)

将父控制器的视图添加到父控制器的视图时,可以在子控制器的视图中定义所需的约束.


Ben*_*air 2

根据以下链接,我将约束创建移至viewWillLayoutSubviews,这是正确设置视图边界的地方。我觉得这个答案错过了为什么子视图控制器的 updateViewConstraints 在父视图控制器之前调用的解释,或者可能只是我的代码中的一些错误,但这个解决方法解决了问题......