Я обнаружил странное поведение в своем приложении, когда подключенный 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
методе, но если содержимое недоступно для изменения, пока оно не появится на экране, это кажется довольно бесполезным. Что могло случиться?
iphone
ios
objective-c
uiscrollview
Джамхин
источник
источник
viewDidLayoutSubviews
был правильный путь. Мне просто нужно было поместить весь мой контент в подпредставление, чтобы метод не вызывался повторно всякий раз, когда я менял фрейм основного представления.Ответы:
Autolayout
внесла огромные изменения в то, как мы проектируем и разрабатываем графический интерфейс наших представлений. Одно из основных отличий заключается в том, чтоautolayout
размеры наших представлений изменяются не сразу, а только при срабатывании, то есть в определенное время, но мы можем заставить его немедленно пересчитать наши ограничения или пометить их как «нуждающиеся в макете». Работает вроде-setNeedDisplay
.Для меня было очень сложно понять и принять тот факт, что нам больше не нужно использовать маски с автоизменением размеров, а фрейм стал бесполезным свойством при размещении наших представлений. Нам больше не нужно думать о позиции просмотра, но мы должны думать, как мы хотим видеть их в пространстве, связанном друг с другом.
Проблемы возникают тогда, когда мы хотим смешать старую маску с автоизменением размера и авторазложением. Мы должны очень скоро подумать о реализации автоматического размещения и постараться не смешивать старый подход в иерархии представлений, основанной на автоматическом размещении.
Допустимо иметь представление контейнера, в котором используются только маски с автоизменением размеров, такие как основное представление контроллера представления, но лучше, если мы не пытаемся смешивать.
Я никогда не использовал раскадровку, но, скорее всего, это правильно. Используя Autolayout, рамки ваших представлений устанавливаются, когда движок autolayout начинает свое вычисление. Попробуйте спросить то же самое сразу после super
- (void)viewDidLayoutSubviews
метода вашего контроллера представления.Этот метод вызывается, когда механизм автоматического раскладки завершает вычисление фреймов ваших представлений.
источник
add something on a screen, "just before it appears to the user". The actual answer is indeed to use viewDidLayoutSubviews.
... ты собираешься показывать это изображение много разИз документации:
Уведомляет контроллер представления о том, что его представление будет добавлено в иерархию представлений.
Уведомляет контроллер представления о том, что его представление было добавлено в иерархию представлений.
В результате фреймы подвидов еще не установлены в
viewWillAppear
:Подходящий метод для изменения вашего пользовательского интерфейса до того, как представление будет представлено на экране :
Уведомляет контроллер представления о том, что его представление только что разместило свои подвиды.
источник
viewDidLayoutSubviews
он будет вызываться несколько раз и не всегда с одним и тем же кадром (я думаю, что иногда он вызывается с помощью CGRectZero при первом вызове). Он вызывается для каждого добавленного подвида и других изменений в представлении.вызов
в вашем
viewWillAppear
методе. После этого вы можете получить доступ к его фрейму, и он будет иметь то же значение, что и вы печатаете вviewDidAppear
источник
В моем случае перемещение всех связанных с кадром методов в
работал отлично (я пытался изменить ограничения из раскадровки).
источник