Подтвердить что ты не робот

Просмотр изменений кадра между 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, но если контент недоступен для меня, чтобы изменить его, пока он не появится на экране, это кажется бесполезным. Что может случиться?

4b9b3361

Ответ 1

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

Ответ 2

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

viewWillAppear:

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

viewDidAppear:

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

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

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

viewDidLayoutSubviews

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

Ответ 3

вызов

self.scrollView.layoutIfNeeded()

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

Ответ 4

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

override func viewWillLayoutSubviews()

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