IOS8 Автоматическая компоновка программно привязана к относительной границе макета

У меня есть элемент пользовательского интерфейса (UISwitch на самом деле, но не имеет значения), который имеет как ведущее, так и конечное пространство, прикрепленное к супервину в Interface Builder. Ограничение похоже на Xcode 6:

Constraint pin

Ограничение для ведущего пространства одинаково эффективно. Значение ограничения 42.0 балла.

Это именно то, что я хочу, потому что для разных устройств я могу изменить свойство layoutMargins на UIView, и ограничения будут работать корректно, чтобы увеличить разницу между представлениями.

Теперь я хочу добавить еще один вид в код, который также будет иметь как ведущее, так и конечное пространство, прикрепленное к нему маркой супервизора, поэтому будет работать тот же самый параметр layoutMargins, который будет отображаться в режиме супервизора.

Я привязал представление, используя язык визуального формата со следующим синтаксисом:

NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|-42.0-[separatorView]-42.0-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(self.contentView, separatorView)];

[self.contentView addConstraints:constraints];
[self.contentView setNeedsUpdateConstraints];

Это работает, но свойство layoutMargins не влияет на это ограничение, поэтому оно явно не привязано к марже, а непосредственно к супервизу.

Итак, мой вопрос:

Как привязать пространства элементов пользовательского интерфейса к марже в коде с использованием языка визуального формата? Или, если это невозможно, как подключиться с помощью constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant: API?

Спасибо!

Ответ 1

В iOS8 язык визуального формата был обновлен, так что "| -" или "- |" по умолчанию будет использовать интервал, определенный свойством layoutMarkins надстройки.

Таким образом, ответ с использованием языка визуального формата выглядит следующим образом:

// programmatically set the layoutMargins, only if
// you want non-default values and they are not already set in IB!
self.contentView.layoutMargins = UIEdgeInsetsMake(0,42,0,42); // set left and right margins to 42

// assume: seperatorView is already a subview of self.contentView

// separatorView will use the constraints because we write "-" between it and the superview edge
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|-[separatorView]-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(separatorView)];
[self.contentView addConstraints:constraints];

Если вы хотите ссылаться на поля макета при создании ограничений с помощью прямого API, то вы используете новые атрибуты макета iOS8:

NSMutableArray * constraints = [NSMutableArray array]; 
[constraints addObject:[NSLayoutConstraint constraintWithItem:self.contentView 
     attribute:NSLayoutAttributeLeftMargin 
     relatedBy:NSLayoutRelationEqual 
     toItem:separatorView
     attribute:NSLayoutAttributeLeft
     multiplier:1.0
     constant:0]];
[constraints addObject:[NSLayoutConstraint constraintWithItem:self.contentView 
     attribute:NSLayoutAttributeRightMargin 
     relatedBy:NSLayoutRelationEqual 
     toItem:separatorView
     attribute:NSLayoutAttributeRight
     multiplier:1.0
     constant:0]];
[self.contentView addConstraints:constraints];

Ответ 2

Я согласен: "В iOS8 язык визуального формата был обновлен, так что" | - "или" - | "по умолчанию будет использовать интервал, определенный свойством layoutMarkins."

Итак, вы должны пометить опцию "Constrains to margin", когда вы используете конструктор Interface, чтобы помочь вашему макету. Если это так, то это действительно работает.

Если проблема все еще не решена, не могли бы вы дать мне демонстрационный проект?

Добавлено: T его статья, которая показывает нам функцию новых API-интерфейсов ios8SuperviewLayoutMargins, желайте, чтобы это было более полезно.