【问题标题】:AutoLayout, Unable to simultaneously satisfy constraintsAutoLayout,无法同时满足约束
【发布时间】:2014-10-27 03:03:34
【问题描述】:

刚开始学习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 上工作

【问题讨论】:

  • 似乎是一组完全合乎逻辑的约束。在过去的几天里,我一直在为类似的事情头疼。顺便说一句,@Chamira Fernando 按钮上还有其他宽度限制吗?内在内容大小等?您是否尝试将compressionResistancePriority 或contentHuggingPriority 设置为高值或低值?看看会发生什么?
  • 约束失败的原因很明显是UIView-Encapsulated-Layout-Width的宽度为0,UIInputView在哪里?
  • 真傻 - 我没看到 (0)。我遇到过同样的问题。它是由 UIInputViewController 提供的 UIInputView - 键盘扩展 (iOS8) 的根视图。我不知道为什么它需要 0 的宽度,考虑到默认行为(根据文档)应该坚持屏幕的宽度。
  • @DevKanchen 就在这里,UIInputView 为零是问题,从技术上讲,默认情况下它至少应该获得键盘可用空间的大小。但事实并非如此。所以我必须根据设备类型和 viewDidLoad 方法中的初始 UIInputView 来获取默认键盘大小。

标签: ios objective-c autolayout


【解决方案1】:

根据您的问题,我了解到您在 nib 中创建了控件并且您直接尝试更改的是您的类的约束。

您可以在这里为视图控制器在 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 时,永远不要直接设置视图的框架。约束用于为您执行此操作。通常,如果您想在视图中设置自己的约束,您应该覆盖 UIView 的 updateConstraints 方法。确保页面控制器的内容视图允许调整其边缘的大小,因为它们的大小将适合页面视图的框架。您的约束和视图设置需要考虑到这一点,否则您将收到无法满足的约束错误。

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

【讨论】:

    【解决方案2】:

    当我尝试在基于 Storyboard 的视图控制器中手动创建所有自动布局约束(在 Swift 中,使用 Snappy - Swift 的 Masonry 端口)时,我不得不与类似的问题作斗争。

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

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

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

    • 选择视图控制器并从菜单中选择Editor > Resolve Auto Layout Issues > All Views in [ ] View Controller > Add Missing Constraints

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

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

    • 从右窗格中选中以下复选框:Placeholder - Remove at build time

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

    【讨论】:

    • 这对我来说完美解决了问题。
    • 我遇到了类似的问题,我有七个 UIButtons 排成一行。在 StoryBoard 中一切都很好,但是当我构建它时,我得到了很多“无法同时满足约束”的异常,但在模拟器上看起来很好。我想知道我是否应该对他们做点什么?如果我这样做了,我将无法使用编辑器解决约束问题,因为我的 StoryBoard 中没有。
    【解决方案3】:

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

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

    • 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
    
    • 再次构建它,现在您可以获得更可读的输出:

    • 获得id 后,您只需在查找导航器中点击它即可:

    • 并快速找到它:

    如何简单地解决这种情况?

    • 尝试将 priority 更改为 999 以防止约束失效。

    在此处查看相关答案:Unable to simultaneously satisfy constraints, will attempt to recover by breaking constraint

    【讨论】:

    • 这是我读过的关于调试约束问题的最有用的东西。把手放下。谢谢!
    • 我同意这是有史以来最好的约束调试技巧。谢谢,Bartlmiej。
    • 感谢您为我节省了大约 5 个小时的生命
    • 谢谢你。对我来说非常重要的帖子。
    • 真的,这个很有用,谢谢
    【解决方案4】:

    这可能没那么难。消息控制台输出显示 UIButton 的约束已重新定义。这意味着就像您放置了一个约束按钮的 HeightWidth 的约束,但您不必要地放置了另一个限制按钮具有Aspect Ratio。在这种情况下,Xcode 无法确定要遵循哪个约束,因此您可以在控制台中看到此调试消息。

    有两种方法对我有用:

    1. 分析控制台中显示的约束,并尝试删除一个或多个约束。

    2.如果您使用storyboardXib,请选择一个约束->显示属性检查器->更改某些约束的优先级。


    还有一件事……

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

    【讨论】:

      【解决方案5】:

      万一其他人遇到这种情况,一个直观地检查约束问题的简单方法是这个网站(它真的很有用!):

      http://www.wtfautolayout.com

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

      【讨论】:

      • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效
      【解决方案6】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-12-28
        • 1970-01-01
        • 2014-06-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多