我的UIViewController
通过覆盖loadView方法创建其视图:
- (void)loadView {
UIView *view = [[UIView alloc] init];
view.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
self.view = view;
}
现在我想切换到AutoLayout,因此添加
view.translatesAutoresizingMaskIntoConstraints = NO;
到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];
}
但我得到一个例外,因为我认为这种约束应该与超级视图一致:
*** 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.
那么,正确的Contraints如何看起来像?
答案 0 :(得分: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];
}
在实践中,您可能想要在超级视图上检查除0约束之外的其他内容,但这应该会有所帮助。
答案 1 :(得分:5)
您不必在根视图上设置约束,因为Matt Neuburg解释了Chapter 19 of his Programming iOS 6 book, in section Manual Layout:
我们并不打算给我们的观点
(self.view)
一个合理的框架。这是因为我们依赖其他人来适当地构建视图。在这种情况下,“其他人”是窗口,它通过将视图控制器的视图适当地设置为根视图,然后将其作为子视图放入窗口之前响应将其rootViewController
属性设置为视图控制器。
答案 2 :(得分:5)
CEarwood方法的问题在于它是一个ViewController,它的视图不是任何其他视图的子视图,因此调用self.view.subview只会导致nil。请记住,Apple文档和指南强烈建议UIViewController或多或少地占据整个屏幕(除了导航栏或标签栏等)。
Palimondo的答案基本上是正确的:你的UIViewController需要在loadView中初始化它的视图,但它不需要指定它的框架或约束,因为它们会自动设置为窗口的框架和约束。如果您没有自己实现loadView,这正是默认情况下完成的操作。
答案 3 :(得分:1)
我不确定您是否需要为窗口的根视图设置约束。
那就是说,你的约束看起来是正确的,我认为你得到的例外是因为:
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[view]|" options:0 metrics:0 views:views]];
使用|表示视图的超级视图的表示法。作为根级别视图,它没有superview。这样的事情可能会更好:
- (void)loadView {
UIView *customView = [[UIView alloc] init];
[self.view addSubview:customView];
NSDictionary* views = @{@"customView" : customView};
[customView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[customView]|" options:0 metrics:0 views:views]];
[customView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[customView]|" options:0 metrics:0 views:views]];
}