在ViewController的loadView中创建的自动调整视图的AutoLayout约束

Tob*_*ler 8 objective-c ios autolayout ios6

UIViewController通过覆盖loadView方法创建它的视图:

- (void)loadView {
    UIView *view = [[UIView alloc] init];
    view.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
    self.view = view;
}
Run Code Online (Sandbox Code Playgroud)

现在我想切换到AutoLayout,因此添加一个

view.translatesAutoresizingMaskIntoConstraints = NO;
Run Code Online (Sandbox Code Playgroud)

到loadView方法.现在我必须指定之前自动生成的相同约束.我的方法是覆盖updateViewConstraints

- (void)updateViewConstraints {
    if (0 == [[self.view constraints] count]) {
        NSDictionary* views = @{@"view" : self.view};

        [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[view]|" options:0 metrics:0 views:views]];
        [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[view]|" options:0 metrics:0 views:views]];
     }

    [super updateViewConstraints];
}
Run Code Online (Sandbox Code Playgroud)

但我得到一个例外,因为我认为这种约束应该与超级视图一致:

*** 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.
Run Code Online (Sandbox Code Playgroud)

那么,正确的Contraints如何看起来像?

CEa*_*ood 8

您需要在superview上设置约束.通过传递"|"引用超级视图引起异常 在视觉格式.如果你更新你的代码如下,它将工作:

- (void)updateViewConstraints {
    if (self.view.superview != nil && [[self.view.superview constraints] count] == 0) {
        NSDictionary* views = @{@"view" : self.view};

        [self.view.superview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[view]|" options:0 metrics:0 views:views]];
        [self.view.superview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[view]|" options:0 metrics:0 views:views]];
    }
   [super updateViewConstraints];
}
Run Code Online (Sandbox Code Playgroud)

在实践中,您可能希望在superview上检查除0约束之外的其他内容,但这应该有所帮助.


Pal*_*ndo 5

您不必在根视图上设置约束,因为Matt Neuburg 在手册布局一节中解释了他的编程iOS 6书第19章:

我们并不打算给我们的观点(self.view)一个合理的框架.这是因为我们依赖其他人来适当地构建视图.在这种情况下,"别人"是窗口,这是为了响应有其rootViewController财产通过适当框架视图控制器的视图,将其放入窗口作为一个子视图前根视图设置为视图控制器.


Ben*_*ler 5

CEarwood方法的问题在于它是一个ViewController,它的视图不是任何其他视图的子视图,因此调用self.view.subview只会导致nil.请记住,Apple文档和指南强烈建议UIViewController或多或少地占据整个屏幕(除了导航栏或标签栏等).

Palimondo的答案基本上是正确的:你的UIViewController需要在loadView中初始化它的视图,但它不需要指定它的框架或约束,因为它们会自动设置为窗口的框架和约束.如果您没有自己实现loadView,这正是默认情况下完成的操作.

  • 有一点错误:你在谈论self.view.superview而不是self.view.subview (4认同)