我是自动布局编程的新手。我试图在点击按钮时创建一个显示/隐藏的视图(按钮)。我能够实现我的目标,但它会引发异常。
这是我的代码:
@interface RootViewController ()
{
NSArray *hiddenState;
NSArray *visibleState;
NSArray *verticalState;
UIButton *btnLeft;
}
- (void)viewDidLoad
{
[super viewDidLoad];
btnLeft = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btnLeft.backgroundColor = [UIColor greenColor];
btnLeft.translatesAutoresizingMaskIntoConstraints = NO;
btnLeft.selected = NO;
[self.view addSubview:btnLeft];
NSString *verticalConstraint = @"V:|[v]|";
NSMutableDictionary *views = [NSMutableDictionary new];
views[@"v"] = btnLeft;
views[@"superview"] = self.view;
if ([self respondsToSelector:@selector(topLayoutGuide)]) {
views[@"topLayoutGuide"] = self.topLayoutGuide;
verticalConstraint = @"V:|[topLayoutGuide][v]|";
}
verticalState = [NSLayoutConstraint constraintsWithVisualFormat:verticalConstraint options:0 metrics:nil views:views];
hiddenState = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[v(==0)]|" options:0 metrics:nil views:views];
visibleState = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[v]-50-|" options:0 metrics:nil views:views];
[self.view addConstraints:verticalState];
[self.view addConstraints:hiddenState];
}
- (IBAction)leftButtonAction:(id)sender
{
UIButton *btn = (UIButton *)sender;
if (btn.selected)
{
[self.view removeConstraints:visibleState];
[self.view addConstraints:hiddenState];
[UIView animateWithDuration:0.5 animations:^{
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
btn.selected = NO;
}];
}
else
{
[self.view removeConstraints:hiddenState];
[self.view addConstraints:visibleState];
[UIView animateWithDuration:0.5 animations:^{
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
btn.selected = YES;
}];
}
}
这会引发以下异常:
以下列表中的至少一个约束可能是您不想要的约束。试试这个:(1)看看每个约束,并试着找出你不期望的东西; (2)找到添加了不需要的约束或约束的代码并修复它。 (注意:如果您正在查看您不了解的NSAutoresizingMaskLayoutConstraints,请参阅UIView属性的文档translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0x7d24d380 H:|-(0)-[UIButton:0x7bf58f70] (Names: '|':UIView:0x7bf4c080 )>",
"<NSLayoutConstraint:0x7d245de0 H:[UIButton:0x7bf58f70(0)]>",
"<NSLayoutConstraint:0x7d245e10 H:[UIButton:0x7bf58f70]-(0)-| (Names: '|':UIView:0x7bf4c080 )>",
"<NSLayoutConstraint:0x7d2ad6f0 'UIView-Encapsulated-Layout-Width' H:[UIView:0x7bf4c080(320)]>"
)
将尝试通过违反约束来恢复
<NSLayoutConstraint:0x7d245e10 H:[UIButton:0x7bf58f70]-(0)-| (Names: '|':UIView:0x7bf4c080 )>
在UIViewAlertForUnsatisfiableConstraints处创建一个符号断点,以便在调试器中捕获它。 UIView中列出的UIVonstraintBasedLayoutDebugging类别中的方法也可能有所帮助。
当我试图使按钮宽度等于零时抛出异常。
答案 0 :(得分:1)
考虑错误消息中的前三个约束:
H:|-(0)-[UIButton:0x7bf58f70] (Names: '|':UIView:0x7bf4c080 )
H:[UIButton:0x7bf58f70(0)]
H:[UIButton:0x7bf58f70]-(0)-| (Names: '|':UIView:0x7bf4c080 )
您的H:|[v(==0)]|
格式字符串会创建这三个约束。我们可以把它们写成这样的方程:
(1) superview.leading == button.leading
(2) button.leading == button.trailing
(3) button.trailing == superview.trailing
将(2)代入(1)得到这个:
(4) superview.leading == button.trailing
然后将(3)代入(4)得到这个:
(5) superview.leading == superview.trailing
这意味着superview的宽度必须为0。
现在考虑错误消息中的最后一个约束:
H:[UIView:0x7bf4c080(320)]
系统添加了这个约束,大概是因为这是根视图控制器的视图因此被调整大小以填充屏幕。该约束表示superview必须具有宽度320.这与等式(5)冲突。这就是你收到错误的原因。
我假设您希望按钮粘贴在超级视图的左边缘,因为您已将其命名为btnLeft
。所以请尝试这些约束:
hiddenState = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[v(==0)]" options:0 metrics:nil views:views];
visibleState = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[v]" options:0 metrics:nil views:views];