在代码中设置约束并不会产生预期的结果

时间:2015-02-15 14:52:21

标签: ios autolayout nsautolayout ios-autolayout

我试图在代码中设置约束而不能获得预期的结果。

我有一个带有3个按钮(子视图)的UIView容器,并且我试图将前导空间设置为其他两个前导空格的平均值(所以&#39 ; ll在中间,水平)。 当我将3个按钮放在我想要的位置时,与我在故事板上看到的数字相比,我得到的数字似乎是正确的。 我通过框架的x值得到了领先的空间(我已经双重检查了aligmentRectForFrame:给出了相同的结果),并且我对它们进行了平均。

我用:

NSLayoutConstraint *twitterConstraint = [NSLayoutConstraint constraintWithItem:middleButton attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:containerView attribute:NSLayoutAttributeLeading multiplier:1.0 constant:average];
[twitterConstraint setPriority:UILayoutPriorityRequired];
[self.view setTranslatesAutoresizingMaskIntoConstraints:NO];
[NSLayoutConstraint activateConstraints:@[twitterConstraint]];

基本功能有效,即如果我输入数字而不是平均值,我会看到结果。我用当前的代码得到了意想不到的结果。特别是,我正在获得"中间按钮"在其他2个按钮的右侧。

帮助!

IDAN

1 个答案:

答案 0 :(得分:0)

扩展@Ken Thomases在评论中回答的原因:自动布局首先从子视图开始收集信息,然后进入超级视图以设置帧。因此,此代码是对其子视图帧的值进行采样,但在执行时(在updateConstraintsupdateViewConstraints或其他地方)这些视图'框架尚未设置为其自动布局批准的值。可能会发生不可预测的结果。

在此视图上调用-layoutIfNeeded会强制Auto Layout引擎为子视图执行此操作 - 请执行布局工作。那么对那些子视图进行采样就可以了。

不幸的是,在这种方法中,会产生问题,既可以对帧进行采样以获取信息,也可以调用layoutIfNeeded,从而复制昂贵的布局操作。如上所述,它需要按钮大小相同。无论如何,这个用例可能都没问题。


使用原生自动布局系统将项目设置为均匀间隔(并允许不同大小的项目)的方法是间隔视图。它不够优雅,但却是必要的。它可以在IB中手动完成,以及如何使用Visual Format Language进行操作:

NSMutableDictionary *autoLayoutDict = [[NSMutableDictionary alloc] init];
NSDictionary *setDictionary = @{
                                @"leftLabel":self.leftLabel,
                                @"middleLabel":self.middleLabel,
                                @"rightLabel":self.rightLabel
                                };
[autoLayoutDict setValuesForKeysWithDictionary:setDictionary];

int numberOfSpacerViewsRequired = 2;
for (int i = 0; i < numberOfSpacerViewsRequired; i++) {

    UIView *spacerViewX = [[UIView alloc] init];
    spacerViewX.backgroundColor = [UIColor clearColor];
    spacerViewX.userInteractionEnabled = NO;
    spacerViewX.translatesAutoresizingMaskIntoConstraints = NO;

    NSString *spacerViewKey = [NSString stringWithFormat:@"spacerView%i", i];
    [autoLayoutDict setObject:spacerViewX forKey:spacerViewKey];

    [self.view addSubview:spacerViewX];
}

NSArray *constraintsToAdd = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[leftLabel]-0-[spacerView0(spacerView1)]-0-[middleLabel]-0-[spacerView1(spacerView0)]-0-[rightLabel]"
                                        options:NSLayoutFormatAlignAllCenterY
                                        metrics:0
                                          views:autoLayoutDict];

[self.view addConstraints:constraintsToAdd];