Autolayout и программные ограничения: как бороться с updateConstraints стрельбы несколько раз?
При программном создании макетов я следую рекомендациям Apple: переопределять -updateConstraints, добавлять пользовательские ограничения и вызывать -setNeedsUpdateConstraints после того, как в представлении добавлены субвью. Моя типичная настройка выглядит так:
- (void)setupViews
{
//Style View
//Add gesture recognizers
//Add Subviews
[self setNeedsUpdateConstraints];
}
- (void)updateConstraints
{
//Add custom constraints
[super updateConstraints];
}
Проблема
Есть случаи, когда -updateConstraints запускается несколько раз (например, когда контроллер представления представлен или помечен w/animation). Проблема здесь в том, что каждое добавленное ограничение добавляется повторно. Это становится серьезной проблемой при попытке по требованию изменить константу добавленного ограничения, так как есть два первоначальных ограничения, которые впоследствии конфликтуют друг с другом. Я предполагаю, что даже когда вы не манипулируете ограничениями после их создания, удваивайте то, что вам кажется нехорошим.
Потенциальные решения
1 - Удалите все ограничения, влияющие на представление перед их применением в -updateConstraints:
- (void)updateConstraints
{
//Remove all constraints affecting view & subviews
//Add custom constraints
[super updateConstraints];
}
2 - Установите флаг макета и проверьте его перед добавлением пользовательских ограничений:
- (void)updateConstraints
{
if (self.didAddConstraints) {
[super updateConstraints];
return;
}
//Add custom constraints
self.didAddConstraints = YES;
[super updateConstraints];
}
3 - Не беспокойтесь о удвоении ограничений, и всякий раз, когда требуется изменить константу, удалите это ограничение перед повторным добавлением.
3 - Что-то удивительное, о котором я не думал.
Какая самая лучшая практика здесь?
Ответы
Ответ 1
Короткий ответ: Потенциальное решение № 2.
Удаление и повторное использование всех ограничений может стать дорогостоящим, поскольку компоновка становится более сложной. Кроме того, если ваш макет имеет состояние, у вас будет больше проблем.
Ограничения удвоения очень неэффективны, вы никогда не знаете, сколько раз может быть вызвано updateConstraints
.
Как этот отчет в блоге показывает, что использование флага - это самый простой и эффективный способ решения этой проблемы. Вот как я сам справляюсь с этим.
Как примечание, вы упоминаете о существовании удивительного способа, о котором вы еще не думали. В большинстве случаев самый простой способ - самый удивительный способ.:)
Ответ 2
Этот вид отслеживания также может быть выполнен для начальной настройки. В большинстве случаев.
override func updateConstraints() {
if constraints.count == 0 {
let views = ["textField": textField]
addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[textField]-0-|", options: [], metrics: nil, views: views))
addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[textField]-0-|", options: [], metrics: nil, views: views))
}
super.updateConstraints()
}