如何在目标c中以编程方式添加约束

时间:2016-02-09 14:29:28

标签: ios autolayout nslayoutconstraint ios-autolayout

我想以编程方式添加约束,并使用下面的代码添加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.

谁能告诉我为什么会出现这个错误? 帮我缩短解决方案

3 个答案:

答案 0 :(得分:9)

在您的情况下,错误明确指出您的视图存在冲突的约束。可能是因为您试图向已经包含Interface Builder的视图添加约束。即使你没有明确设置任何约束,IB也会在检测到某些约束失踪时为你提供这些约束。

我在评论中看到你提到你想以编程方式完成所有事情。在这种情况下,请看一段代码:

- (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不能完全描述它的位置。

结果:

enter image description here

我鼓励您尝试使用Visual Format Language。使用更少的代码可以实现相同的结果。这段代码导致了同样的结果:

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

如果这有帮助,请告诉我。欢呼声。

答案 1 :(得分:1)

问题不在于您的代码,而在于IB auto generated at build time for view with fixed frame消息:

如果您不自行添加,

Interface Builder会自动为您生成约束。 你可以通过

来避免它
  • 在Project Navigator中选择笔尖或故事板,转到文件检查器并取消选中Use Auto Layout

  • 在Interface Builder中添加一些约束并将其设置为remove at build time

答案 2 :(得分:0)

看起来你有相互冲突的布局限制。最有可能在故事板中设置约束,并且您尝试以编程方式添加与其直接冲突的约束。

看起来你正试图在动作发生后将UIView移开。 I.E按下按钮,将快乐的脸部图片从屏幕中间移动到左上角。

直接在代码中添加和删除约束可能是一个巨大的问题,代码膨胀,单元测试和警告填满了你的控制台。

在故事板中创建主UIView可能是一个更好的主意,并且有一个隐藏的占位符UIView,它包含你按下按钮后想要UIView所具有的所有约束。然后,您可以以编程方式为这些UIViews切换出所有约束。因此,您要修改的视图将具有占位符的位置,宽度和高度,占位符将具有您要修改的视图的位置和高度。

这样,在以编程方式更改布局约束时,您将永远不会出现此错误,因为故事板会捕获任何错误。

有一些开源可以通过一行或两行代码为您完成此操作。 (文档中还有一些youtube视频教程)https://cocoapods.org/pods/SBP

安装cocoapod后,您的代码看起来像这样

这将是视图控制器内的代码,其中包含要修改的UIView和占位符UIView

//UIView* viewBeforeChange
//UIView* hiddenViewAfterChange
[self switchViewConst:viewBeforeChange secondView:hiddenViewAfterChange];