ios AutoLayout,无法同时满足约束

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25630315/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 02:10:04  来源:igfitidea点击:

AutoLayout, Unable to simultaneously satisfy constraints

iosobjective-cnsautolayout

提问by Chamira Fernando

Just started learning iOS AutoLayout, Interface builder very straight forward, but when I try to archive the same thing on the code

刚开始学习 iOS AutoLayout,Interface builder 非常简单,但是当我尝试在代码上归档相同的东西时

    [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)]];

it raises an exception,

它引发了一个异常,

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)
(
 "<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']>

All 4 buttons .translatesAutoresizingMaskIntoConstraints = NO;

所有 4 个按钮 .translatesAutoresizingMaskIntoConstraints = NO;

I wonder what is wrong ? help is really appreciated :)

我想知道怎么了?真的很感激帮助:)

FYI: I work on iOS8 SDK

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

回答by Bart?omiej Semańczyk

The easiest way how to find unsatisfiable constraints:

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

  • set unique identifier for every constraint in your view:
  • 为视图中的每个约束设置唯一标识符:

enter image description here

enter image description here

  • create simple extension for NSLayoutConstraint:
  • 创建简单的扩展NSLayoutConstraint

SWIFT:

斯威夫特

extension NSLayoutConstraint {

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

OBJECTIVE-C

目标-C

@interface NSLayoutConstraint (Description)

@end

@implementation NSLayoutConstraint (Description)

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

@end
  • build it once again, and now you have more readable output for you:
  • 再次构建它,现在你有更多可读的输出给你:

enter image description here

enter image description here

  • once you got your idyou can simple tap it in your Find Navigator:
  • 获得后,您id可以在Find Navigator 中简单地点击它:

enter image description here

enter image description here

  • and quickly find it:
  • 并快速找到它:

enter image description here

enter image description here

HOW TO SIMPLE FIX THAT CASE?

如何简单地解决这个问题?

  • try to change priorityto 999for broken constraint.
  • 尝试改变优先级,以999断开的约束。

See the related answer here: Unable to simultaneously satisfy constraints, will attempt to recover by breaking constraint

请参阅此处的相关答案:无法同时满足约束,将尝试通过打破约束来恢复

回答by Markus Rautopuro

I had to struggle with similar problem when I was trying to manually create all the auto layout constraints (in Swift, using Snappy - a Masonry port to Swift) in a view controller that is based on a Storyboard.

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

For some reason, Xcode generates own default set of auto layout constraints on a NIB at build time. This is why I couldn't add any more manual constraints, because they were conflicting with the automatically added ones.

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

I resolved this the following way:

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

  • Open up the Storyboard view controller you're handling.

  • Select the view controller and select Editor > Resolve Auto Layout Issues > All Views in [ ] View Controller > Add Missing Constraintsfrom the menu:

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

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

enter image description here

enter image description here

(This will ensure that no additional build time constraints are created and all the constraints are now visible.)

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

  • Select all the constraints from your view controller:
  • 从视图控制器中选择所有约束:

enter image description here

enter image description here

  • Check from the right pane the following check box: Placeholder - Remove at build time:
  • 从右侧窗格中选中以下复选框:Placeholder - Remove at build time

enter image description here

enter image description here

Now you can add all the auto layout constraints manually in the code.

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

回答by lynulzy

It may be not so difficult.The message console output says that the UIButton's constraints redefined.It means just like that you put a constraint that restrict the Heightand the Widthof the button, but needlessly you put another restriction that the button has a Aspect Ratio.In this condition Xcode can't make sure which constraint to follow,so that you can see this debug message in console.

可能没那么难。消息控制台输出说重新定义了 UIButton 的约束。这意味着就像你设置了一个约束来限制按钮的HeightWidth,但是你不必要地设置了另一个限制按钮有一个Aspect Ratio。在这个条件 Xcode 无法确定要遵循哪个约束,因此您可以在控制台中看到此调试消息。

There are two ways Useful for me:

有两种方法对我有用:

  1. Analyse the constraints displayed in the console,and try to delete one or more constraint.
  1. 分析控制台中显示的约束,并尝试删除一个或多个约束。

2.If you are using the storyboardor Xib,Select a constraint ->Show the Attributes Inspector -> change the priority of some Constraints.

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



One more thing...

还有一件事...

You can follow the articleof Jason Jarrett. Add a symbol breakpoint to make sure which view make the error happen.

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

回答by JoniVR

In case anyone else runs into this, an easy way to visually check for problems with your constraints is this site (it's really useful!):

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

http://www.wtfautolayout.com

http://www.wtfautolayout.com

Here's the Github project in case the site goes down: https://github.com/johnpatrickmorgan/wtfautolayout

这是 Github 项目,以防网站宕机:https: //github.com/johnpatrickmorgan/wtfautolayout

回答by JoniVR

According to your question what i've understood that you have created control in nib and you are?directly trying to change is constraints from your class.

根据您的问题,我了解到您已经在 nib 中创建了控件,并且您正在尝试更改的是您班级的约束。

What you can do here is set constraints in nib for view controller and then bind it with your class and use objects of constraints. Or you can create view?programmatically and directly set the constraints.

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

// You also need to check that whether you need to “translatesAutoresizingMaskIntoConstraints” if “YES - the view's superview looks at the view's autoresizing mask, produces constraints that implement it, and adds those constraints to itself (the superview).” and if “NO - the view's superview does not looks at the view's autoresizing mask, and not produces constraints that implement it.”

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

I also got same issue and I fixed it as following

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

     [_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)]];

? ? So when using AutoLayout, you should never directly set the frame of a view. Constraints are used to do this for you. Normally if you want to set your own constraints in a view, you should override the?updateConstraintsmethod of your UIViews. Make sure the content views for the page controller allow for their edges to be resized since they will be sized to fit the page view's frame. Your constraints and view setup will need to account for this, or you you will get unsatisfiable constraint errors.

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

https://developer.apple.com/library/mac/documentation/userexperience/conceptual/AutolayoutPG/AutoLayoutConcepts/AutoLayoutConcepts.html#//apple_ref/doc/uid/TP40010853-CH14-SW1You can also refer above link of apple to in-depth study and if you still face issue i'll be try my level best to solve you issue. ?

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