如何在目标 c 中以编程方式添加约束
Posted
技术标签:
【中文标题】如何在目标 c 中以编程方式添加约束【英文标题】:How to add Constraint programmatically in objective c 【发布时间】:2016-02-09 14:29:28 【问题描述】:我想以编程方式添加约束,我使用下面的代码来添加 TOP 和 LEFT 约束。
NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:label1
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTop
multiplier:1
constant:110];
NSLayoutConstraint *left = [NSLayoutConstraint constraintWithItem:label1
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeLeading
multiplier:1
constant:10];
lable1
被添加到我的视图控制器中。当我在视图中添加这两个约束时,例如
[self.view addConstraint:top];
[self.view addConstraint:left];
它给出了consol中的错误,并且约束不影响标签。
2016-02-09 19:36:59.824 testinMRC[99160:313382] 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.
(
"<NSLayoutConstraint:0x7fa5c8738610 V:|-(110)-[UILabel:0x7fa5c8626940'Label'] (Names: '|':UIView:0x7fa5c86267b0 )>",
"<NSIBPrototypingLayoutConstraint:0x7fa5c8628a70 'IB auto generated at build time for view with fixed frame' V:|-(88)-[UILabel:0x7fa5c8626940'Label'] (Names: '|':UIView:0x7fa5c86267b0 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7fa5c8738610 V:|-(110)-[UILabel:0x7fa5c8626940'Label'] (Names: '|':UIView:0x7fa5c86267b0 )>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2016-02-09 19:36:59.889 testinMRC[99160:313382] 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.
(
"<NSLayoutConstraint:0x7fa5c87334b0 H:|-(10)-[UILabel:0x7fa5c8626940'Label'] (Names: '|':UIView:0x7fa5c86267b0 )>",
"<NSIBPrototypingLayoutConstraint:0x7fa5c86285c0 'IB auto generated at build time for view with fixed frame' H:|-(188)-[UILabel:0x7fa5c8626940'Label'](LTR) (Names: '|':UIView:0x7fa5c86267b0 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7fa5c87334b0 H:|-(10)-[UILabel:0x7fa5c8626940'Label'] (Names: '|':UIView:0x7fa5c86267b0 )>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
谁能告诉我为什么会出现这个错误? 帮我缩短解决方案
【问题讨论】:
使用砌体以编程方式添加约束。 此处添加的最新方式:***.com/a/51531647/4061501 【参考方案1】:在您的情况下,错误清楚地表明您的视图有冲突的约束。可能是因为您试图将约束添加到已经有一些来自 Interface Builder 的视图。即使您没有明确设置任何约束,IB 也会在检测到某些约束缺失时为您提供这些约束。
我在 cmets 中看到您提到您希望以编程方式完成所有操作。在这种情况下,请查看一段代码:
- (void)viewDidLoad
[super viewDidLoad];
UIView *view = [UIView new];
view.backgroundColor = [UIColor redColor];
[view setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addSubview:view];
NSLayoutConstraint *left = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1 constant:100];
NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1 constant:100];
NSLayoutConstraint *height = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:50];
NSLayoutConstraint *width = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:50];
[self.view addConstraints:@[left, top]];
[view addConstraints:@[height, width]];
这是不言自明的。如您所见,我必须为视图添加宽度和高度约束,因为只有 left 和 top 并不能完全描述它的位置。
结果:
我鼓励您尝试视觉格式语言。使用更少的代码可以实现相同的结果。此代码导致完全相同的结果:
NSArray *horizontal = [NSLayoutConstraint constraintsWithVisualFormat:@"|-100-[view(50)]" options:0 metrics:nil views:@@"view" : view];
NSArray *vertical = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-100-[view(50)]" options:0 metrics:nil views:@@"view" : view];
[self.view addConstraints:vertical];
[self.view addConstraints:horizontal];
如果这有帮助,请告诉我。干杯。
【讨论】:
[view setTranslatesAutoresizingMaskIntoConstraints:NO];
这是一个关键要求。【参考方案2】:
问题不是你的代码,而是IB auto generated at build time for view with fixed frame
消息:
如果您不自己添加约束,Interface Builder 会自动为您生成约束。 您可以通过以下任一方式避免它
在项目导航器中选择笔尖或情节提要,转到文件检查器并取消选中Use Auto Layout
。
或
在 Interface Builder 中添加一些约束并将它们设置为remove at build time
。
【讨论】:
第一个选项,取消选中Use Auto Layout
,可能会对项目产生巨大而彻底的影响,并要求 OP 切换到旧的“支柱和弹簧”样式调整大小。添加缺少的约束并将它们标记为“在构建时删除”的第二个选项似乎是一个更好的解决方案。
我想创建标签运行时间。在运行时创建标签时,上面的代码是否正确。【参考方案3】:
您的布局约束似乎有冲突。很可能在情节提要中设置了约束,而您正尝试以编程方式添加与它直接冲突的约束。
看起来您正试图在操作发生后将 UIView 移开。即按一个按钮,将一张笑脸图片从屏幕中间移动到左上角。
直接在代码中添加和删除约束可能会让人头疼,因为代码膨胀、单元测试和警告会填满您的控制台。
在故事板中创建主 UIView 并拥有一个隐藏的占位符 UIView 可能是一个更好的主意,它包含您希望 UIView 在按下按钮后具有的所有约束。然后,您可以以编程方式为这些 UIView 切换所有约束。所以你要修改的视图会有占位符的位置、宽度和高度,占位符会有你要修改的视图的位置和高度。
这样,您在以编程方式更改布局约束时将永远不会出现此错误,因为情节提要会捕获任何错误。
有一些开源软件可以通过一两行代码为您完成这项工作。 (文档中也有一些 youtube 视频教程)https://cocoapods.org/pods/SBP
安装 cocoapod 后,您的代码将如下所示
这将是视图控制器内的代码,其中包含您要修改的 UIView 和占位符 UIView
//UIView* viewBeforeChange
//UIView* hiddenViewAfterChange
[self switchViewConst:viewBeforeChange secondView:hiddenViewAfterChange];
【讨论】:
以上是关于如何在目标 c 中以编程方式添加约束的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Swift 中以编程方式在水平线上设置约束? [关闭]
如何在 ios swift 中以编程方式创建自动布局等宽约束?