Установка ограничений в коде не дает ожидаемого результата

Я пытаюсь установить ограничение в коде и не получить ожидаемый результат.

У меня есть контейнер 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]];

основная функциональность работает, то есть, если я поставлю число вместо среднего, я вижу результаты. Я получаю неожиданные результаты с текущим кодом. в частности, я получаю "среднюю кнопку" на правой стороне двух других кнопок.

Помогите!

Идан

1 ответ

Более подробно о том, почему @Ken Thomases отвечает в комментариях, работает: автоматическая компоновка сначала переходит из подпредставления для сбора информации, а затем переходит в суперпредставление для установки фреймов. Таким образом, этот код является выборкой значений своих кадров подвид, но во время его выполнения (в updateConstraints или же updateViewConstraints или где-то еще) кадрам этих представлений еще не присвоены значения, одобренные автоматическим макетом. Могут произойти непредсказуемые результаты.

Вызов -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];
Другие вопросы по тегам