如何在目标 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 中以编程方式添加约束的主要内容,如果未能解决你的问题,请参考以下文章

如何在iOS中以编程方式从UIButton中删除等宽约束

目标 C:以编程方式添加带有约束的 UI 按钮

如何在 Swift 中以编程方式在水平线上设置约束? [关闭]

如何在 ios swift 中以编程方式创建自动布局等宽约束?

如何在特定文件夹中的 iCloud 上传图像并在目标 C 中以编程方式访问该特定文件夹

如何在ios swift中以编程方式创建自动布局等宽度约束?