使用自动布局约束编程

12

我希望能在我的iOS应用中以编程方式使用自动布局。

我有一个简单的视图控制器,其中包含以下初始化代码:

UIView *innerView = [[UIView alloc] initWithFrame:self.view.bounds];

UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button1 setFrame:CGRectMake(50, 50, 150, 50)];
[button1 setTitle:@"button1" forState:UIControlStateNormal];

UIButton *button2 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button2 setFrame:CGRectMake(250, 50, 150, 50)];
[button2 setTitle:@"button2" forState:UIControlStateNormal];

[innerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[button1][button2(==button1)]|" options:NSLayoutFormatAlignAllBaseline metrics:0 views:NSDictionaryOfVariableBindings(button1, button2)]];

[innerView addSubview:button1];
[innerView addSubview:button2];
[self.view addSubview:innerView];

但是当我尝试运行这个程序时,出现了以下错误:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unable to parse constraint format: 
Unable to interpret '|' character, because the related view doesn't have a superview 
|[button1][button2(==button1)]| 
          ^'

有什么问题吗?

当我尝试在constraintsWithVisualFormat中删除管道时,我收到了此警告:

Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSAutoresizingMaskLayoutConstraint:0x716be10 h=--& v=--& UIRoundedRectButton:0x71631f0.midX == + 325>",
    "<NSAutoresizingMaskLayoutConstraint:0x7169940 h=--& v=--& H:[UIRoundedRectButton:0x715fb80(150)]>",
    "<NSAutoresizingMaskLayoutConstraint:0x7169860 h=--& v=--& UIRoundedRectButton:0x715fb80.midX == + 125>",
    "<NSLayoutConstraint:0x7164cd0 UIRoundedRectButton:0x71631f0.width == UIRoundedRectButton:0x715fb80.width>",
    "<NSLayoutConstraint:0x7164940 H:[UIRoundedRectButton:0x715fb80]-(0)-[UIRoundedRectButton:0x71631f0]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7164940 H:[UIRoundedRectButton:0x715fb80]-(0)-[UIRoundedRectButton:0x71631f0]>

Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

由此导致我的限制根本没有任何效果。我做错了什么?
2个回答

34

你有三个问题:

首先,你需要在两个按钮子视图上选择启用基于布局的约束。

[button1 setTranslatesAutoresizingMaskIntoConstraints:NO];
[button2 setTranslatesAutoresizingMaskIntoConstraints:NO]; 

这将消除NSAutoresizingMaskLayoutConstraint错误。现在,您可以着手处理布局约束的问题。

其次,在添加约束之前,您必须先addSubview。在内部视图(innerView)调用addContraints之前,您应该将button1和button2作为innerView的子视图添加。

第三,您应该指定(尽管文档表明这是可选的)布局字符串是垂直还是水平的。@"H:|[button1][button2(==button1)]|"。您还需要一个垂直约束,如@"V:[button1]|",它将button1与innerview底部对齐,并因为您已经在按钮上对齐了基线,button2将跟随button1所在位置。


1
是的,setTranslatesAutoresizingMaskIntoConstraints:NO 帮助我摆脱了这些错误。但是结果是我得到了一个按扭2对齐在左上角(按扭1不可见),而且我仍然不能在 visualFormat 中使用管道符号。你有任何想法为什么错误说 related view doesn't have a superview?UIViewController 的 self.view 不是我的 innerView 的父视图吗? - kallax
2
"related view doesn't have a superview" 是因为您正在添加涉及尚未插入视图层次结构的视图的约束。请在所有调用addSubview:之后移动addConstraints:调用。 - escrafford
谢谢,当我将带有约束的代码块移动到“addSubview”语句下面时,关于“无法解释管道”的错误消失了,并且我得到了类似于我想要的布局。)谢谢,问题已经解决了。) - kallax
在添加子视图后添加约束是否有任何额外的注意事项?当解决约束时,是否存在闪烁的可能性,或者iOS系统是否在幕后以某种方式处理这个问题? - Thomas Clowes

2
仅供参考:有关缺少superview的异常,已经由constraintsWithVisualFormat而不是addConstraints触发。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接