嵌入 UIViewController 的子容器的自动布局

Auto layout of a Child Container that embeds a UIViewController

我的主场景显示了一个子 UIViewController,方法是在其视图中放置一个子容器,并在该子容器中嵌入一个子 UIViewController。我通过按住 ctrl 键从子容器拖动到 storyboard 中的子 UIViewController,然后选择 "embed" segue。

这让我可以在其他地方封装和重用子 UIViewController。我认为这是相当标准的。但是我不能让它正确地自动布局。

我做了一个简单的测试用例来证明这一点: https://github.com/murraycu/ios-example-autolayout-of-child-container-views

它有两个 UIViewControllers 嵌入在选项卡控制器中,因此您可以在它们之间切换。

"Simple" 选项卡显示 SimpleViewController,其中显示图像和标签,在故事板中可见:

UIImage 或 UILabel 均未指定高度约束,但它们具有等宽(等于父视图)约束以保持宽度简单。

UILabel 显然不是很高,但 UIImage 和 UILabel 的 Content Hugging 优先级略有不同,因此根据自动布局,它们的高度不会模糊。因此,多亏了自动布局,当我在运行时将其文本设置为一些需要更多 space 的文本时,它会占用更多 space,从而使 space 远离其上方的 UIImage。很好 - 这是我想要的行为,如在模拟器中所见:

现在问题来了:"With Child Container" 选项卡显示 WithChildContainerViewController,它显示相同的图像但显示我的 ChildViewController(嵌入在子容器中)而不是 UILabel。嵌入的 ChildViewController 显示 UILabel。它在情节提要中:

但是,自动布局系统现在似乎不知道子容器需要多少 space 才能在我的 ChildViewController 中显示标签中的所有文本。与 "Simple" 选项卡中一样,UIImage 或子容器都没有指定高度约束。现在 XCode 抱怨 "Height is ambiguous for " 容器视图”。在模拟器中看起来像这样:

如果我向子容器添加约束,将其底部限制在父视图的底部,这会有所改善,正如@iphonic 所建议的:https://github.com/murraycu/ios-example-autolayout-of-child-container-views/commit/1d295fe0a6c4502764f8725d3b99adf8dab6b9ae 但高度仍然错误:

如何让自动布局系统知道要做什么?我考虑过实现 UIView 的 intrinsicContentSize,但 UIViewController 不是 UIView。

建议是,以编程方式而不是通过 IB。见下文

 _childController=[self.storyboard instantiateViewControllerWithIdentifier:@"ChildController"];

    [self addChildViewController:_childController];
    [_container addSubview:_childController.view];
    [_childController didMoveToParentViewController:self];

    _childController.view.frame=_container.bounds;


    //add constraints        
    UIView *subView=_childController.view;
    UIView *parent=_container;


    subView.translatesAutoresizingMaskIntoConstraints=NO;

    NSLayoutConstraint *width =[NSLayoutConstraint
                                    constraintWithItem:subView
                                    attribute:NSLayoutAttributeWidth
                                    relatedBy:0
                                    toItem:parent
                                    attribute:NSLayoutAttributeWidth
                                    multiplier:1.0
                                    constant:0];
    NSLayoutConstraint *height =[NSLayoutConstraint
                                     constraintWithItem:subView
                                     attribute:NSLayoutAttributeHeight
                                     relatedBy:0
                                     toItem:parent
                                     attribute:NSLayoutAttributeHeight
                                     multiplier:1.0
                                     constant:0];
   NSLayoutConstraint *top = [NSLayoutConstraint
                                   constraintWithItem:subView
                                   attribute:NSLayoutAttributeTop
                                   relatedBy:NSLayoutRelationEqual
                                   toItem:parent
                                   attribute:NSLayoutAttributeTop
                                   multiplier:1.0f
                                   constant:0.f];

NSLayoutConstraint *leading = [NSLayoutConstraint
                                           constraintWithItem:subView
                                           attribute:NSLayoutAttributeLeading
                                           relatedBy:NSLayoutRelationEqual
                                           toItem:parent
                                           attribute:NSLayoutAttributeLeading
                                           multiplier:1.0f
                                           constant:0.f];
    [parent addConstraint:width];
    [parent addConstraint:height];
    [parent addConstraint:top];
    [parent addConstraint:leading];

希望对您有所帮助。

干杯。

@iphonic 的代码但使用可视格式语言

_childController = [self.storyboard instantiateViewControllerWithIdentifier: @"ChildController"];

[self addChildViewController: _childController];
[_container addSubview: _childController.view];
[_childController didMoveToParentViewController: self];

//add constraints
NSDictionary *views = @{@"subView": _childController.view, 
                        @"parent": _container};

[parent addConstraints:[NSLayoutConstraint
                        constraintsWithVisualFormat: @"V:|[subView(==parent)]"
                        options: 0
                        metrics: nil
                        views: views]];

[parent addConstraints: [NSLayoutConstraint
                         constraintsWithVisualFormat:@"H:|[subView(==parent)]"
                         options: 0
                         metrics: nil
                         views: views]];