ios - 自动布局问题

标签 ios iphone objective-c autolayout autorotate

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

  1. 第 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. 第 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];
    }
    

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

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) ( "UIView:0x8a461c0 (Names: '|':UIWindow:0x8a42970 )>", "", "", "UIButton:0x8a45ea0 (Names: '|':UIView:0x8a461c0 )>", "" )

Will attempt to recover by breaking constraint

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

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

最佳答案

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


一些旁白:

  1. 如果使用 Storyboard/NIBS,您应该删除以下行:

    self.view.translatesAutoresizingMaskIntoConstraints = NO;
    

    但请保留以下内容:

    _button1.translatesAutoresizingMaskIntoConstraints = NO;
    
  2. 我对全面取消所有限制持谨慎态度。我通常保留要删除的约束的数组,这样我就可以轻松删除那些我需要删除并将要重建的约束。在您的情况下,删除所有内容可能没问题,但是当您向 View 添加越来越多的约束时,跟踪您想要删除和重建的内容可能会更容易:

    @property (nonatomic, strong) NSArray *verticalConstraints;
    @property (nonatomic, strong) NSArray *horizontalConstraints;
    
  3. 我可能建议使用 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];
    }
    

关于ios - 自动布局问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20331148/

相关文章:

ios - 你如何创建一个对象的 NSMutableArray,它不会增加添加到它的每个对象的保留计数?

iOS - 一个 SegmentedControl - 多个 ViewControllers

ios - requestTestAccountTokensWithArraysOfPermissions FBSDK 4.x 版本

ios - 从 DKAssets 获取视频

iphone - 特定iPhone应用程序创建的难度级别?

objective-c - CALayer frame origin.y翻转了,0在最下面?

ios - ios Objective C 应用程序上的 AVPlayer 无法播放视频

objective-c - Xcode 错误 : Expected identifier

iphone - PhoneGap 和 Appcelerator 在本地和远程存储数据?

ios - 使用 UIAlertController 阻塞循环