Изменения кадра просмотра между 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()
работал отлично (я пытался изменить ограничения из раскадровки).