自动布局约束警告“将尝试通过打破约束来恢复”
Posted
技术标签:
【中文标题】自动布局约束警告“将尝试通过打破约束来恢复”【英文标题】:Autolayout constraints warning "Will attempt to recover by breaking constraint" 【发布时间】:2014-08-03 18:26:21 【问题描述】:当应用程序在此设备上运行时,我正在为 iPhone 4 设置一些具体限制。就对齐和一切而言,一切看起来都很棒。
但是,我的所有约束都出现了错误,我试图通过打破约束来恢复它们。
当它检测到它是否是 iPhone 4 时,在我的 viewDidLoad 中调用此方法
- (void) addConstraints
// removing automatic system constraints
[self.view removeConstraints:self.view.constraints];
[self.view setTranslatesAutoresizingMaskIntoConstraints:NO];
NSDictionary *views = NSDictionaryOfVariableBindings(appBackground, myCustomer, myItemDetails, myItemQuantity, myItemPrice, myNext, myBtn); // UIImageView, UITextField, UIButton
for (UIView *view in [views allValues])
view.translatesAutoresizingMaskIntoConstraints = NO;
NSDictionary *metrics = @@"width": @210.0, @"height": @42.0, @"verticalSpacing": @34;
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[appBackground]|"
options:0
metrics:nil
views:views];
constraints = [constraints arrayByAddingObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[appBackground]|"
options:0
metrics:nil
views:views]];
constraints = [constraints arrayByAddingObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(85)-[myCustomer(==height)]-(verticalSpacing)-[myItemDetails(==height)]-(verticalSpacing)-[myItemQuantity(==height)]-(verticalSpacing)-[myItemPrice(==height)]-(18)-[myNext(==35)]-(71.5)-[myBtn(==50)]-(7.5)-|"
options:0
metrics:metrics
views:views]];
constraints = [constraints arrayByAddingObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-50-[myCustomer(==width)]-|"
options:0
metrics:metrics
views:views]];
constraints = [constraints arrayByAddingObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-50-[myItemDetails(==width)]-|"
options:0
metrics:metrics
views:views]];
constraints = [constraints arrayByAddingObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-50-[myItemQuantity(==width)]-|"
options:0
metrics:metrics
views:views]];
constraints = [constraints arrayByAddingObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-50-[myItemPrice(==width)]-|"
options:0
metrics:metrics
views:views]];
constraints = [constraints arrayByAddingObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-78-[myNext(==173)]-|"
options:0
metrics:metrics
views:views]];
constraints = [constraints arrayByAddingObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-11.5-[myBtn(==54)]-|"
options:0
metrics:metrics
views:views]];
[self.view addConstraints:constraints];
错误!
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:0xb8282f0 H:|-(50)-[UITextField:0xb823fc0] (Names: '|':UIView:0xb82f360 )>",
"<NSLayoutConstraint:0xb828320 H:[UITextField:0xb823fc0(210)]>",
"<NSLayoutConstraint:0xb82be10 H:[UITextField:0xb823fc0]-(NSSpace(20))-| (Names: '|':UIView:0xb82f360 )>",
"<NSLayoutConstraint:0xb82d3d0 H:|-(78)-[UIButton:0xb82ad50] (Names: '|':UIView:0xb82f360 )>",
"<NSLayoutConstraint:0xb82d420 H:[UIButton:0xb82ad50(173)]>",
"<NSLayoutConstraint:0xb82d450 H:[UIButton:0xb82ad50]-(NSSpace(20))-| (Names: '|':UIView:0xb82f360 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xb82d450 H:[UIButton:0xb82ad50]-(NSSpace(20))-| (Names: '|':UIView:0xb82f360 )>
Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2014-08-03 14:03:29.239 iReceipt[2886:607] 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:0xb8282f0 H:|-(50)-[UITextField:0xb823fc0] (Names: '|':UIView:0xb82f360 )>",
"<NSLayoutConstraint:0xb828320 H:[UITextField:0xb823fc0(210)]>",
"<NSLayoutConstraint:0xb82be10 H:[UITextField:0xb823fc0]-(NSSpace(20))-| (Names: '|':UIView:0xb82f360 )>",
"<NSLayoutConstraint:0xb82d480 H:|-(11.5)-[UIButton:0xb820120] (Names: '|':UIView:0xb82f360 )>",
"<NSLayoutConstraint:0xb82e390 H:[UIButton:0xb820120(54)]>",
"<NSLayoutConstraint:0xb82e3c0 H:[UIButton:0xb820120]-(NSSpace(20))-| (Names: '|':UIView:0xb82f360 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xb82e3c0 H:[UIButton:0xb820120]-(NSSpace(20))-| (Names: '|':UIView:0xb82f360 )>
如果你们需要更多信息,请告诉我..
【问题讨论】:
【参考方案1】:这三个约束:
"<NSLayoutConstraint:0xb8282f0 H:|-(50)-[UITextField:0xb823fc0] (Names: '|':UIView:0xb82f360 )>",
"<NSLayoutConstraint:0xb828320 H:[UITextField:0xb823fc0(210)]>",
"<NSLayoutConstraint:0xb82be10 H:[UITextField:0xb823fc0]-(NSSpace(20))-| (Names: '|':UIView:0xb82f360 )>",
规定超级视图为 50 + 210 + 20 == 280 点宽。
这三个约束:
"<NSLayoutConstraint:0xb82d3d0 H:|-(78)-[UIButton:0xb82ad50] (Names: '|':UIView:0xb82f360 )>",
"<NSLayoutConstraint:0xb82d420 H:[UIButton:0xb82ad50(173)]>",
"<NSLayoutConstraint:0xb82d450 H:[UIButton:0xb82ad50]-(NSSpace(20))-| (Names: '|':UIView:0xb82f360 )>"
规定同一个超级视图为 78 + 173 + 20 == 271 点宽。
显然,这两者不可能同时为真。你需要决定你真正想要在这里发生的事情。我们无法读懂你的想法,UIKit 也一样。
通常,您不会在按钮上设置宽度限制;您让它使用其固有大小和适当的优先级来实现内容拥抱和抗压缩。此外,您可能不希望在按钮的任一侧设置硬间距。要么让该间距不受约束地变化,因此按钮可以是其固有大小,降低该约束的优先级使其是可选的,或者进行不等式以便您具有最小间距但不是精确间距。
【讨论】:
所以,问题之一是当我设置垂直约束 'V:|-(85)-[myCustomer(==height)]-(verticalSpacing)-[myItemDetails(==height) ]-(verticalSpacing)-[myItemQuantity(==height)]-(verticalSpacing)-[myItemPrice(==height)]-(18)-[myNext(==35)]-(71.5)-[myBtn(== 50)]-(7.5)-|'一下子? 您发布的问题是水平约束,而不是垂直约束。但是,如果您的超级视图不完全是85+3*(height+verticalSpacing)+height+18+35+71.5+50+7.5
点高,您将在垂直方向遇到类似的问题。正如 Ken 所说,您应该在约束中尽可能多地增加灵活性。
那部分代码是关于垂直布局的,而冲突是由于水平布局造成的。给定宽度,UIButton
似乎是您的myNext
。 UITextField
可以是它们中的任何一个,因为它们以相同的方式受到约束。不过,我不得不说,总体而言,您似乎过于拘束。我不知道超级视图与屏幕的关系是什么,但是您正在口授一切。这里没有处理不同屏幕尺寸或方向等的灵活性。
好的。但我实际上并不想提供更多的灵活性,因为我不会支持横向模式,我只希望字段和按钮在 iPhone 4 上运行时具有精确的宽度和高度以匹配我的 UI 设计
那你为什么要使用自动布局?【参考方案2】:
你限制了你的观点太多。例如,您必须始终让 leftmargin、width 和 rightmargin 之一保持灵活,并让自动布局引擎拉伸那个。
没有任何数字的单破折号表示默认距离,即 20 像素。因此,如果您删除
上的尾随约束@"H:|-78-[myNext(==173)]-|"
@"H:|-11.5-[myBtn(==54)]-|"
并将它们更改为
@"H:|-78-[myNext(==173)]"
@"H:|-11.5-[myBtn(==54)]"
然后布局引擎将拉伸按钮的右边距以使其适合 包含视图。当然,还有其他方法可以放松这些限制,一切都取决于您的设计目标。
就个人而言,我不再使用标准 API:s 进行自动布局。我使用了库PureLayout,它非常好地抽象了自动布局!
【讨论】:
没有破折号表示“零距离”,而不是“任意距离”。您的更改不会使任何事情变得更灵活。如果您希望它灵活,您可以完全放弃尾随关系(例如@"H:|-78-[myNext(==173)]"
)。
啊,谢谢,我就是这个意思。我会编辑我的答案以上是关于自动布局约束警告“将尝试通过打破约束来恢复”的主要内容,如果未能解决你的问题,请参考以下文章
自动布局警告:将尝试通过在 CollectionView 中打破约束 <NSLayoutConstraint 来恢复