我正在开发一个使用自动布局的应用程序。我正在执行以下步骤:

  • 步骤1:在viewDidLoad中创建一个按钮
    [super viewDidLoad];
    
    self.view.translatesAutoresizingMaskIntoConstraints = NO;
    
    _button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    _button1.translatesAutoresizingMaskIntoConstraints = NO;
    [_button1 setTitle:@"B" forState:UIControlStateNormal];
    [self.view addSubview:_button1];
    
  • 步骤2:在updateViewConstraints方法中实现约束
    [super updateViewConstraints];
    
    [self.view removeConstraints:self.view.constraints];
    
    if (UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation))
    {
        NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:_button1 attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0f constant:100.0f];
        [self.view addConstraint:constraint];
    
        NSLayoutConstraint *constraint1 = [NSLayoutConstraint constraintWithItem:_button1 attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0f constant:-100.0f];
        [self.view addConstraint:constraint1];
    
        NSLayoutConstraint *constraint2 = [NSLayoutConstraint constraintWithItem:_button1 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0f constant:200.0f];
        [self.view addConstraint:constraint2];
    
        NSLayoutConstraint *constraint3 = [NSLayoutConstraint constraintWithItem:_button1 attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0f constant:-100.0f];
        [self.view addConstraint:constraint3];
    
    
        _button1.backgroundColor = [UIColor redColor];
    } else{
        NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:_button1 attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0f constant:200.0f];
        [self.view addConstraint:constraint];
    
        NSLayoutConstraint *constraint1 = [NSLayoutConstraint constraintWithItem:_button1 attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0f constant:-200];
        [self.view addConstraint:constraint1];
    
        NSLayoutConstraint *constraint2 = [NSLayoutConstraint constraintWithItem:_button1 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0f constant:50.0f];
        [self.view addConstraint:constraint2];
    
        NSLayoutConstraint *constraint3 = [NSLayoutConstraint constraintWithItem:_button1 attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0f constant:-50.0f];
        [self.view addConstraint:constraint3];
    
        _button1.backgroundColor = [UIColor blueColor];
    }
    

  • 但是当我切换设备方向时,控制台将打印以下内容:

    无法同时满足约束条件。大概至少一个
    以下列表中的约束之一是您不想要的约束。尝试
    这:(1)查看每个约束,并尝试找出哪个约束
    没想到(2)找到添加了不必要约束的代码或
    约束并修复它。 (注意:如果您看到
    您不了解的NSAutoresizingMaskLayoutConstraints,请参阅
    到UIView属性的文档
    平移AutoresizingMaskIntoConstraints)(
    “UIView:0x8a461c0(名称:'|':UIWindow:0x8a42970)>”,
    “”,
    “”,
    “UIButton:0x8a45ea0(名称:'|':UIView:0x8a461c0)>”,
    “”)

    将尝试通过打破约束来恢复


    中断objc_exception_throw以在调试器中捕获此错误。的
    UIView上的UIConstraintBasedLayoutDebugging类别中的方法
    列出的内容也可能会有帮助。

    谁能告诉我这种布局有什么问题吗?

    最佳答案

    问题是您在仍然对按钮有约束的情况下在[super updateViewConstraints]中调用updateViewConstraints。因此,当您从横向过渡到纵向时,您仍然具有横向按钮约束(纵向无法满足),但是要求主视图更新其(人像)约束。如果在删除所有现有的按钮约束后将调用移至[super updateViewConstraints]的任何位置,则您的状态应良好。

    几个方面:

  • 如果使用情节提要/ NIBS,则应删除显示以下内容的行:
    self.view.translatesAutoresizingMaskIntoConstraints = NO;
    

    但请保留以下内容:
    _button1.translatesAutoresizingMaskIntoConstraints = NO;
    
  • 我会警惕大规模删除所有约束的情况。我通常会保留要删除的约束数组,这样一来,我可以轻松删除仅需要删除并将要重构的约束。在您的情况下,删除所有内容可能没问题,但是随着您向视图中添加越来越多的约束,跟踪要删除和重建的对象可能更容易:
    @property (nonatomic, strong) NSArray *verticalConstraints;
    @property (nonatomic, strong) NSArray *horizontalConstraints;
    
  • 我可能建议使用VFL,这更加简洁:
    - (void)updateViewConstraints
    {
        if (self.horizontalConstraints)
            [self.view removeConstraints:self.horizontalConstraints];
    
        if (self.verticalConstraints)
            [self.view removeConstraints:self.verticalConstraints];
    
        [super updateViewConstraints];
    
        NSDictionary *views   = NSDictionaryOfVariableBindings(_button1);
        NSDictionary *metrics = nil;
    
        if (UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation))
        {
            metrics = @{@"left"   : @100,
                        @"right"  : @100,
                        @"top"    : @200,
                        @"bottom" : @100};
    
            _button1.backgroundColor = [UIColor redColor];
        } else{
            metrics = @{@"left"   : @200,
                        @"right"  : @200,
                        @"top"    : @50,
                        @"bottom" : @50};
    
            _button1.backgroundColor = [UIColor blueColor];
        }
    
        self.horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(left)-[_button1]-(right)-|" options:0 metrics:metrics views:views];
        self.verticalConstraints   = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(top)-[_button1]-(bottom)-|" options:0 metrics:metrics views:views];
        [self.view addConstraints:self.horizontalConstraints];
        [self.view addConstraints:self.verticalConstraints];
    }
    
  • 09-12 09:16