代码添加constraint,设置translatesAutoresizingMaskIntoConstraints为NO的原因

当在代码中添加NSLayoutConstraint时,可能会遇到约束冲突的错误。解决方法是在对应视图上调用`setTranslatesAutoresizingMaskIntoConstraints:NO`。这行代码的作用是禁用视图的自动布局转换约束,以防止由于隐式约束和手动添加的约束之间的冲突导致的问题。在不使用自动布局的视图作为使用自动布局的视图的子视图时,如果不设置为NO,会导致默认的约束与手动添加的约束冲突。虽然视图仍能显示,但可能造成显示问题。使用`setTranslatesAutoresizingMaskIntoConstraints:NO`可以避免这种冲突,但需要确保手动添加足够的约束以定义视图的位置和大小。在某些情况下,如批量创建相似的UI元素时,代码添加约束比Storyboard更方便。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在用代码为控件添加NSLayoutConstraint的时候,有时会遇到以下错误:

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) 

这种错误在编译阶段又无法被查出。这时,我们在检查了自己的constraint之后,确认constraint没有逻辑错误,可能就是没有在对应的view添加以下代码

[view setTranslatesAutoresizingMaskIntoConstraints:NO];

那这一行代码有何作用呢?

在Programming IOS 7(第四版)有这么一段话:

Layout is performed in three primary ways:

Manual layout

       The superview is sent the layoutSubviews message whenever it is resized; so, to

       lay out subviews manually, provide your own subclass and override layout-

       Subviews. Clearly this could turn out to be a lot of work, but it means you can do

       anything you like.

Autoresizing

......

Autolayout

......

就是说layout有三种方式:Manual layout,Autoresizing,Autolayout。我们常用的可能就后面两种。

假设v1是一个不使用autolayout的view,而v2是一个使用autolayout的view,但v1成为v2的subview时,

v2需要四条隐含的constraint来确定v1的位置,这些约束都是从v1的frame转化而来:

This conversion is performed only if the view in question has its translates-

AutoresizingMaskIntoConstraints property set to YES. That is, in fact, the default if

the view came into existence either in code or by instantiation from a nib where “Use

Auto Layout” is not checked. The assumption is that if a view came into existence in

either of those ways, you want its frame and autoresizingMask to act as its constraints

if it becomes involved in autolayout.



- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self.view setTranslatesAutoresizingMaskIntoConstraints:NO];
    self.v1 = [[UIView alloc]initWithFrame:CGRectMake(200, 200, 100, 100)];
    self.v1.backgroundColor = [UIColor greenColor];
    
    self.v2 = [UIView new];
    self.v2.backgroundColor = [UIColor redColor];
    [self.view addSubview:self.v2];
    self.v2.translatesAutoresizingMaskIntoConstraints = NO;
    //self.v1.translatesAutoresizingMaskIntoConstraints = NO;
    NSDictionary * viewDic = [[NSDictionary alloc]initWithObjectsAndKeys:self.v2,@"v2", self.v1,@"v1",nil];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-100-[v2]-100-|" options:0 metrics:nil views:viewDic]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-100-[v2]-100-|" options:0 metrics:nil views:viewDic]];
    
    
    [self.v2 addSubview:self.v1];
    [self.v2 addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-100-[v1]-100-|" options:0 metrics:nil views:viewDic]];

}


上面代码会产生以下错误(Unable to simultaneously satisfy constraints.) ,即不能满足所有约束。容易看出,添加在v2上的constraint没有问题。是v1的隐含constraint和后来添加的constriaint产生了冲突



但是v1还能显示,(这个问题还没想明白):



但是去掉下面这一行的注释,再运行

//self.v1.translatesAutoresizingMaskIntoConstraints = NO;
v1无法显示:


显然,v1在translatesAutoresizingMaskIntoConstraints 设置为NO之后,没有添加隐含constraint,而代码添加的constraint又不足以确定v1的位置和大小,所以v1无法显示;



由于代码添加constraint很难检查出错误,所以我尽量避免代码编写constraint。但storyboard有时操作又比较麻烦,且不够灵活,有时就需要自己添加部分的代码来弥补storyboard的不足。

比如,我们要添加十几个按钮,这些按钮功能有基本一致,样式也一样,这时用storyboard编写就显得麻烦。以下代码向一个view中添加了12个按钮。并设置了他们的constraint

<span style="font-size:14px;">- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self.view setTranslatesAutoresizingMaskIntoConstraints:NO];
    NSDictionary * keyDetail;
    UIView * secondItem = self.view;
    keyDetail = [[NSDictionary alloc]initWithObjectsAndKeys:
                 @"F1",@"101",
                 @"F2",@"102",
                 @"F3",@"103",
                 @"F4",@"104",
                 @"F5",@"105",
                 @"F6",@"106",
                 @"F7",@"107",
                 @"F8",@"108",
                 @"F9",@"109",
                 @"F10",@"110",
                 @"F11",@"111",
                 @"F12",@"112",
                 nil];
    CGFloat keyHeightParameter = 30.0;
    CGFloat keyWidthParameter = 10;
    CGFloat keyspaceHorizontal = keyWidthParameter*keyDetail.count/(keyDetail.count+1);
    CGFloat keyspaceVertical = 200.0;
    int i;
    for(i = 1; i <= keyDetail.count; i++)
    {
        UIButton * key = [[UIButton alloc]init];
        key.tag = i+100 ;
        
        [key setTranslatesAutoresizingMaskIntoConstraints:NO];
        
        [key setTitle:[keyDetail valueForKey:[NSString stringWithFormat:@"%i",i+100]] forState:UIControlStateNormal];
        [key setTitleColor:[UIColor colorWithRed:49.0/255.0 green:69.0/255.0 blue:116.0/255.0 alpha:1.0] forState:UIControlStateNormal];
        [key setTitleColor:[UIColor colorWithRed:49.0/255.0 green:69.0/255.0 blue:116.0/255.0 alpha:1.0] forState:UIControlStateSelected];
        key.titleLabel.font = [UIFont systemFontOfSize:14.0];
        [key setBackgroundColor:[UIColor whiteColor]];
        key.layer.borderColor = [UIColor grayColor].CGColor;
        key.layer.borderWidth = 0.5;
        key.layer.cornerRadius = 10;
        
        [self.view addSubview:key];
        if (secondItem == self.view)
        {
            [self.view addConstraint:[NSLayoutConstraint constraintWithItem:key attribute:NSLayoutAttributeLeading
                                                                  relatedBy:NSLayoutRelationEqual
                                                                     toItem:secondItem
                                                                  attribute:NSLayoutAttributeLeading
                                                                 multiplier:1 constant:keyspaceHorizontal]];
        }
        else
        {
            [self.view addConstraint:[NSLayoutConstraint constraintWithItem:key attribute:NSLayoutAttributeLeading
                                                                  relatedBy:NSLayoutRelationEqual
                                                                     toItem:secondItem
                                                                  attribute:NSLayoutAttributeTrailing
                                                                 multiplier:1 constant:keyspaceHorizontal]];
        }
        
        [self.view addConstraint:[NSLayoutConstraint constraintWithItem:key attribute:NSLayoutAttributeTop
                                                              relatedBy:NSLayoutRelationEqual
                                                                 toItem:self.view attribute:NSLayoutAttributeTop
                                                             multiplier:1.0 constant:keyspaceVertical]];
        [self.view addConstraint:[NSLayoutConstraint constraintWithItem:key
                                                              attribute:NSLayoutAttributeWidth
                                                              relatedBy:NSLayoutRelationEqual
                                                                 toItem:self.view attribute:NSLayoutAttributeWidth
                                                             multiplier:1.0/keyDetail.count constant:-keyWidthParameter]];
        [key addConstraint:[NSLayoutConstraint constraintWithItem:key
                                                        attribute:NSLayoutAttributeHeight
                                                        relatedBy:NSLayoutRelationEqual
                                                           toItem:nil
                                                        attribute:NSLayoutAttributeNotAnAttribute
                                                       multiplier:1.0 constant:keyHeightParameter]];
        
        secondItem = key;
    }
}</span>

效果如下:

landscape:



portrait:



在这个过程中遇到一个错误:

        The view hierarchy is not prepared for the constraint:

        这种错误一般都是constrain与控件不对应,或者是subview没有加到superview中。



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值