Изменения кадра просмотра между viewWillAppear: и viewDidAppear:

Я обнаружил странное поведение в моем приложении, где подключен IBOutlet имеет связанный кадр просмотра между вызовами в моем контроллере представления viewWillAppear: а также viewDidAppear:, Вот соответствующий код в моем UIViewController подкласс:

-(void)viewWillAppear:(BOOL)animated {
    NSLog(@"%@", self.scrollView);
}

-(void)viewDidAppear:(BOOL)animated {
    NSLog(@"%@", self.scrollView);
}

и полученный лог вывод:

MyApp[61880:c07] <UIScrollView: 0x1057eff0; frame = (0 0; 0 0); clipsToBounds = YES; autoresize = TM+BM; gestureRecognizers = <NSArray: 0x10580100>; layer = <CALayer: 0x1057f210>; contentOffset: {0, 0}>
MyApp[61880:c07] <UIScrollView: 0x1057eff0; frame = (0 44; 320 416); clipsToBounds = YES; autoresize = TM+BM; gestureRecognizers = <NSArray: 0x10580100>; layer = <CALayer: 0x1057f210>; contentOffset: {0, 0}>

Что наглядно показывает, что кадр меняется между двумя вызовами. Я хотел сделать настройку с представлением в viewDidLoad метод, но если контент недоступен для меня, пока он не появится на экране, это кажется довольно бесполезным. Что может происходить?

4 ответа

Решение

Autolayout сделал огромное изменение в том, как мы проектируем и разрабатываем графический интерфейс наших взглядов. Одним из основных отличий является то, что autolayout не изменяет размеры нашего вида сразу, а только при срабатывании, это означает, что в определенное время, но мы можем заставить его немедленно пересчитать наши ограничения или пометить их как "нуждающиеся" в макете. Работает как -setNeedDisplay,
Для меня большой проблемой было понять и принять это, нам больше не нужно использовать маски с автоматическим изменением размера, и фрейм стал бесполезным свойством при размещении наших представлений. Нам больше не нужно думать о позиции обзора, но мы должны думать о том, как мы хотим видеть их в пространстве, связанном друг с другом.
Когда мы хотим смешать старую маску авторазмера и автопоставку, это когда возникают проблемы. Мы должны очень скоро подумать о реализации автоматического размещения и постараться не смешивать старый подход в иерархии представлений, основанной на автоматическом размещении.
Хорошо иметь контейнерное представление, которое использует только маски с автоматическим изменением размера, такие как основной вид контроллера представления, но лучше, если мы не пытаемся смешивать.
Я никогда не использовал раскадровку, но, скорее всего, это правильно. Используя Autolayout, рамки ваших представлений устанавливаются, когда движок autolayout начинает свои вычисления. Попробуйте спросить то же самое сразу после супер - (void)viewDidLayoutSubviews метод вашего просмотра контроллера.
Этот метод вызывается, когда движок autolayout завершил вычисление фреймов ваших представлений.

Из документации:

viewWillAppear:

Уведомляет контроллер представления о том, что его представление собирается добавить в иерархию представлений.

viewDidAppear:

Уведомляет контроллер представления, что его представление было добавлено к иерархии представления.

В результате кадры подпредставлений еще не установлены в viewWillAppear:

Подходящий метод для изменения вашего пользовательского интерфейса перед представлением на экране:

viewDidLayoutSubviews

Уведомляет контроллер представления, что его представление только что выложило его подпредставления.

Вызов

self.scrollView.layoutIfNeeded()

в вашем viewWillAppear метод. После этого вы можете получить доступ к его кадру, и он будет иметь то же значение, что и в viewDidAppear

В моем случае перемещение всех методов, связанных с кадрами, в

override func viewWillLayoutSubviews()

работал отлично (я пытался изменить ограничения из раскадровки).

Другие вопросы по тегам