Ios 在代码中设置约束不会';我们不能产生预期的结果

Ios 在代码中设置约束不会';我们不能产生预期的结果,ios,autolayout,ios-autolayout,Ios,Autolayout,Ios Autolayout,我试图在代码中设置约束,但没有得到预期的结果 我有一个UIVIEW容器,有3个按钮(子视图),我试图把一个人的前导空间设置为其他两个前导空间的平均值(因此它将位于中间,水平)。 当我把3个按钮放在我想要的位置时,与我在故事板上看到的数字相比,我得到的数字似乎是正确的。 我通过帧的x值得到前导空间(我仔细检查了aligmentRectForFrame:是否给出了相同的结果),然后对它们进行平均 我使用: NSLayoutConstraint *twitterConstraint = [NSLayo

我试图在代码中设置约束,但没有得到预期的结果

我有一个UIVIEW容器,有3个按钮(子视图),我试图把一个人的前导空间设置为其他两个前导空间的平均值(因此它将位于中间,水平)。 当我把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]];
基本功能有效,即如果我输入一个数字,而不是平均值,我会看到结果。我用当前代码得到了意想不到的结果。具体地说,我在其他两个按钮的右侧得到了“中间按钮”

救命啊


idan

进一步阐述了@Ken Thomases在评论工作中回答问题的原因:自动布局首先从子视图向上收集信息,然后从superview向下设置帧。因此,此代码正在对其子视图帧的值进行采样,但在执行时(在
updateConstraints
updateViewConstraints
或其他地方),这些视图帧尚未设置为其自动布局批准的值。不可预测的结果可能发生

在此视图上调用-layoutIfNeeded将强制自动布局引擎对子视图执行此操作——实际上是执行布局工作。因此,对这些子视图进行采样是可行的

不幸的是,在这种方法中,会产生问题,包括对帧进行采样以获取信息和调用layoutIfNeeded,这会重复昂贵的布局操作。如前所述,它要求按钮的大小都相同。不管怎样,对于这个用例来说可能是好的


使用本机自动布局系统(并允许不同大小的项目)将项目设置为均匀间隔的方法是间隔视图。这是不雅的,但却是必要的。可以在IB中手动完成,下面介绍如何使用Visual Format语言完成:

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];
NSMutableDictionary*autoLayoutDict=[[NSMutableDictionary alloc]init];
NSDictionary*setDictionary=@{
@“leftLabel”:self.leftLabel,
@“middleLabel”:self.middleLabel,
@“rightLabel”:self.rightLabel
};
[autoLayoutDict setValuesForKeysWithDictionary:setDictionary];
int numberOfSpacerViewsRequired=2;
对于(int i=0;i
对不起,我不明白-您将平均值设置为多少?在获取现有按钮的帧之前,您是否强制布局?NIB中的值可能与运行时的值非常不同。无论如何,查询帧以计算自动布局常量似乎不是一个好主意。(例如,前导并不总是与X坐标相同。此外,如果按钮的宽度不同,则将一个前导放在其他两个按钮之间不会使其居中。)可以直接使用centerX属性使按钮相对于superview居中。您可以使用宽度设置为相等的间隔视图相对于同级创建相等的空间。平均值是其他按钮引导空间的平均值@Ken-我确实通过interface builder在我感兴趣的按钮上强制引入空格,其优先级低于我在代码中设置的优先级。这三个按钮的大小完全相同。我还仔细检查了使用aligmentRectForFrame:得到的结果是否与使用x坐标得到的结果相同。此外,我得到的x值等于我在Interface Builder中看到的前导空格。在我看来,我的计算的所有“组成部分”都如预期的那样,即使如此,最终结果也并非如此。还有其他想法吗?我所说的“强制布局”是在包含视图上调用
-layoutifneed
。你是在检查框架之前做的吗?就是这样!谢谢你,肯!