可能至少以下列表中的一个约束是您不想要的约束

时间:2014-10-07 13:12:20

标签: ios autolayout

我是自动布局编程的新手。我试图在点击按钮时创建一个显示/隐藏的视图(按钮)。我能够实现我的目标,但它会引发异常。

这是我的代码:

@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类别中的方法也可能有所帮助。

当我试图使按钮宽度等于零时抛出异常。

1 个答案:

答案 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];