AutoLayout,无法同时满足约束

时间:2014-09-02 18:52:32

标签: ios objective-c nsautolayout

刚开始学习iOS AutoLayout,界面构建器非常直接,但是当我尝试在代码上存档相同的东西时

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(==2)-[_nextKeyboardButton]-(==2)-[_numPadButton]-(==2)-[_spaceButton]-(==2)-[_returnButton]-(==2)-|" options:0 metrics:0 views:NSDictionaryOfVariableBindings(_nextKeyboardButton,_numPadButton,_spaceButton,_returnButton)]];

它引发了一个例外,

无法同时满足约束条件。

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)
(
 "<NSLayoutConstraint:0x6000000966c0 H:|-(2)-[UIButton:0x7fe4f1d1c760'Next']   (Names: '|':UIInputView:0x7fe4f1f04d00 )>",
 "<NSLayoutConstraint:0x600000096710 H:[UIButton:0x7fe4f1d1c760'Next']-(2)-[UIButton:0x7fe4f1d1d1d0'123']>",
 "<NSLayoutConstraint:0x600000096760 H:[UIButton:0x7fe4f1d1d1d0'123']-(2)-[UIButton:0x7fe4f1d1d6f0'Space']>",
 "<NSLayoutConstraint:0x6000000967b0 H:[UIButton:0x7fe4f1d1d6f0'Space']-(2)-[UIButton:0x7fe4f1d1d8d0'Return']>",
 "<NSLayoutConstraint:0x600000096800 H:[UIButton:0x7fe4f1d1d8d0'Return']-(2)-|   (Names: '|':UIInputView:0x7fe4f1f04d00 )>",
 "<NSLayoutConstraint:0x600000096e40 'UIView-Encapsulated-Layout-Width' H:[UIInputView:0x7fe4f1f04d00(0)]>"
 )

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x6000000967b0 H:[UIButton:0x7fe4f1d1d6f0'Space']-(2)-[UIButton:0x7fe4f1d1d8d0'Return']>

所有4个按钮.translatesAutoresizingMaskIntoConstraints = NO;

我想知道出了什么问题?非常感谢帮助:)

仅供参考:我在iOS8 SDK上工作

6 个答案:

答案 0 :(得分:80)

如何找到不可满足的约束的最简单方法:

  • 为视图中的每个约束设置唯一标识符:

enter image description here

  • NSLayoutConstraint
  • 创建简单扩展程序

SWIFT

extension NSLayoutConstraint {

    override public var description: String {
        let id = identifier ?? ""
        return "id: \(id), constant: \(constant)" //you may print whatever you want here
    }
}

<强>目的-C

@interface NSLayoutConstraint (Description)

@end

@implementation NSLayoutConstraint (Description)

-(NSString *)description {
    return [NSString stringWithFormat:@"id: %@, constant: %f", self.identifier, self.constant];
}

@end
  • 再次构建它,现在您有更多可读输出:

enter image description here

  • 获得id后,您可以在查找导航器中轻松点击它:

enter image description here

  • 并迅速找到它:

enter image description here

如何简单地修复案例?

  • 尝试将优先级更改为999以获取损坏的约束。

请参阅此处的相关答案:Unable to simultaneously satisfy constraints, will attempt to recover by breaking constraint

答案 1 :(得分:8)

当我尝试在基于故事板的视图控制器中手动创建所有自动布局约束(在Swift中,使用Snappy - 一个到Swift的Masonry端口)时,我不得不遇到类似的问题。

出于某种原因,Xcode在构建时在NIB上生成自己的默认自动布局约束集。这就是我无法添加任何手动约束的原因,因为它们与自动添加的约束相冲突。

我通过以下方式解决了这个问题:

  • 打开您正在处理的Storyboard视图控制器。

  • 选择视图控制器并选择编辑器&gt;解决自动布局问题&gt; []视图控制器中的所有视图&gt;从菜单中添加缺失约束

enter image description here

(这将确保不会创建额外的构建时间约束,现在所有约束都可见。)

  • 从视图控制器中选择所有约束:

enter image description here

  • 从右侧窗格中选中以下复选框:占位符 - 在构建时删除

enter image description here

现在,您可以在代码中手动添加所有自动布局约束。

答案 2 :(得分:3)

可能不是那么困难。消息控制台输出说UIButton的约束被重新定义。这意味着就像你设置限制HeightWidth的约束一样。按钮,但不必要的另外一个限制是按钮有一个Aspect Ratio。在这种情况下,Xcode不能确定要遵循哪个约束,这样你就可以在控制台中看到这个调试消息。

有两种方式对我有用:

  1. 分析控制台中显示的约束,并尝试删除一个或多个约束。
  2. 2.如果您使用storyboardXib,请选择约束 - &gt;显示属性检查器 - &gt;改变一些约束的优先级。

    还有一件事......

    你可以关注Jason Jarrett的article。添加符号断点以确保哪个视图发生错误。

答案 3 :(得分:3)

如果有其他人遇到此问题,可以通过这种方式直观地检查您的约束问题(这非常有用!):

http://www.wtfautolayout.com

如果网站出现故障,这是Github项目: https://github.com/johnpatrickmorgan/wtfautolayout

答案 4 :(得分:2)

根据你的问题,我知道你已经在笔尖中创建了控件,并且你正在直接尝试改变你班级的约束。

你可以在这里做的是在视图控制器的nib中设置约束,然后将它与你的类绑定并使用约束对象。或者,您可以以编程方式创建视图并直接设置约束。

//如果“是 - 视图的超视图查看视图的自动调整掩码,生成实现它的约束,并将这些约束添加到自身(超级视图)”,您还需要检查是否需要“translatesAutoresizingMaskIntoConstraints”。如果“否 - 视图的超级视图不会查看视图的自动调整掩码,也不会生成实现它的约束。”

我也遇到了同样的问题,我将其修复为以下

     [_nextKeyboardButton setTranslatesAutoresizingMaskIntoConstraints:YES];
    _numPadButton.translatesAutoresizingMaskIntoConstraints = YES;
    [_numPadButton updateConstraints];
    [_nextKeyboardButton updateConstraints];

    NSArray *constraints2 = [NSLayoutConstraint
                             constraintsWithVisualFormat:@"H:|-57-[_nextKeyboardButton(96)]"
                             options:0
                             metrics:nil
                             views:NSDictionaryOfVariableBindings(_nextKeyboardButton)];

    [self.view addConstraints:constraints2];

    NSArray *constraints4 = [NSLayoutConstraint
                             constraintsWithVisualFormat:@"V:|-123-[_nextKeyboardButton(30)]"
                             options:0
                             metrics:nil
                             views:NSDictionaryOfVariableBindings(_nextKeyboardButton)];

    [self.view addConstraints:constraints4];

    NSArray *constraints1 = [NSLayoutConstraint
                             constraintsWithVisualFormat:@"H:|-207-[_numPadButton(58)]"
                             options:0
                             metrics:nil
                             views:NSDictionaryOfVariableBindings(_numPadButton)];

    [self.view addConstraints:constraints1];

    NSArray *constraints3 = [NSLayoutConstraint
                             constraintsWithVisualFormat:@"V:|-123-[_numPadButton(30)]"
                             options:0
                             metrics:nil
                             views:NSDictionaryOfVariableBindings(_numPadButton)];

    [self.view addConstraints:constraints3];

// Create Controls  or view programmatically.

UILabel *label = [UILabel new];
    label.text = @"This is a Label";
    label.font = [UIFont systemFontOfSize:18];
    label.backgroundColor = [UIColor lightGrayColor];
    label.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:label];

    NSArray *constraints = [NSLayoutConstraint
                            constraintsWithVisualFormat:@"V:|-offsetTop-[label(100)]"
                            options:0
                            metrics:@{@"offsetTop": @100}
                            views:NSDictionaryOfVariableBindings(label)];
    [self.view addConstraints:constraints];

    UIView *spacer1 = [UIView new];
    spacer1.translatesAutoresizingMaskIntoConstraints = NO;
    [spacer1 setBackgroundColor:[UIColor redColor]];
    [self.view addSubview:spacer1];

    UIView *spacer2 = [UIView new];
    spacer2.translatesAutoresizingMaskIntoConstraints = NO;
    [spacer2 setBackgroundColor:[UIColor greenColor]];
    [self.view addSubview:spacer2];

    NSArray *constraints1 = [NSLayoutConstraint
                            constraintsWithVisualFormat:@"V:|-offsetTop-[spacer1(100)]"
                            options:0
                            metrics:@{@"offsetTop": @100}
                            views:NSDictionaryOfVariableBindings(spacer1)];

    [self.view addConstraints:constraints1];

    NSArray *constraints2 = [NSLayoutConstraint
                             constraintsWithVisualFormat:@"V:|-offsetTop-[spacer2(100)]"
                             options:0
                             metrics:@{@"offsetTop": @100}
                             views:NSDictionaryOfVariableBindings(spacer2)];

    [self.view addConstraints:constraints2];

    [self.view addConstraints:[NSLayoutConstraint
                               constraintsWithVisualFormat:@"H:|[spacer1]-10-[label]-20-[spacer2(==spacer1)]|"
                               options:0
                               metrics:nil
                               views:NSDictionaryOfVariableBindings(label, spacer1, spacer2)]];

因此,在使用AutoLayout时,您不应该直接设置视图的框架。约束用于为您执行此操作。通常,如果要在视图中设置自己的约束,则应覆盖UIViews的updateConstraints方法。确保页面控制器的内容视图允许调整其边缘大小,因为它们的大小将适合页面视图的框架。您的约束和视图设置需要考虑到这一点,否则您将得到不可满足的约束错误。

https://developer.apple.com/library/mac/documentation/userexperience/conceptual/AutolayoutPG/AutoLayoutConcepts/AutoLayoutConcepts.html#//apple_ref/doc/uid/TP40010853-CH14-SW1 您也可以参考苹果的上述链接进行深入研究,如果您仍然面临问题,我将尽力为您解决问题。

答案 5 :(得分:0)

我通过NSLayoutConstraint.deactivate(MystackView.constraints)解决了我的问题