Автозапуск в UITextField: автоматический макет еще требуется после выполнения -layoutSubviews

Я подклассифицирую UITextField, чтобы добавить ярлык с левой стороны. Я использую автозапуск для компоновки ярлыка. Тем не менее, я продолжаю получать этот сбой:

Вот как я делаю свой код макета:

- (void)updateConstraints {

self.segmentLabel.translatesAutoresizingMaskIntoConstraints = NO;

NSLayoutConstraint *constraint;
constraint = [NSLayoutConstraint constraintWithItem:self.segmentLabel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0.0f];
[self addConstraint:constraint];
constraint = [NSLayoutConstraint constraintWithItem:self.segmentLabel attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0.0f];
[self addConstraint:constraint];
constraint = [NSLayoutConstraint constraintWithItem:self.segmentLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0f];
[self addConstraint:constraint];
constraint = [NSLayoutConstraint constraintWithItem:self.segmentLabel attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:self.segmentWidth];
[self addConstraint:constraint];

[super updateConstraints];

}

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

Однако, если я попытаюсь установить текст заполнителя, я получаю это исключение:

Завершение приложения из-за неперехваченного исключения "NSInternalInconsistencyException", причина: "Автоматическая компоновка по-прежнему требуется после выполнения -layoutSubviews. Реализация DDSegmentedTextField для -layoutSubviews требует вызова super. '

Однако я не переопределяю -layoutSubviews.

Кто-нибудь сталкивался с этим? Что я делаю неправильно?

Спасибо!

Ответы

Ответ 1

Итак, я столкнулся с этой же ошибкой несколько дней назад. Оказывается, я пытался разбить субвью внутри моего подкласса UITextfield, установив на них свойства, перемещая их и т.д., Но никогда не указывал явному представлению (т.е. Вызывал [self layoutIfNeeded]).

iOS 8, по-видимому, заставляет взглянуть на макет всех своих подзонов, а затем настраивает ограничения на него. iOS 7 не будет, и вам нужно явно указывать представления для перерисовки своих подзонов при изменении, если вы используете автозапуск.

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

- (void)setLabelText:(NSString *)newText{
    self.sideLabel.text = newText;
}

Это вызвало сбой моего приложения, когда появился контроллер представления, содержащий мое текстовое поле с подклассом. Добавив layoutIfNeeded, все теперь отлично работает в iOS7 и iOS8.

- (void)setLabelText:(NSString *)newText{
    self.sideLabel.text = newText;
    [self layoutIfNeeded];
}

Это нужно вызывать каждый раз, когда вы изменяете часть представления в своем подклассе. Это включает настройку, когда вы добавляете subviews, когда вы меняете свойства вида, что-либо действительно. Перед тем, как функция, которая изменит ваше представление, вернется, вызовите layoutIfNeeded в своем представлении. Это похоже на несколько стандартных элементов управления пользовательского интерфейса, включая UITextfield, UITableView и UICollectionView, хотя я уверен, что есть и другие. Я надеюсь, что это было достаточно ясно и помогло решить вашу проблему.

Ошибка, которую вы получаете, не очень полезна и даже не применима в моем случае. Хотя я получал точно такую ​​же ошибку, ни один из моих представлений не реализовал layoutSubviews, и поэтому все они использовали метод [super layoutSubviews].

Ответ 2

Эта проблема появляется в iOS < 8

При создании подкласса UIView и добавлении представлений мы можем поручить элементу управления построить и автозапуск сначала подвью. Используйте этот оператор, когда пользовательский интерфейс необходимо обновить:

[self layoutIfNeeded];

iOS 8+ отлично справляются с проблемой, если они есть внутри.

Ответ 3

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