UIViewController viewDidLoad некорректная ширина/высота
Всем известно, что вы не можете доверять размеру фрейма в методе init/viewDidLoad UIViewController; это:
- (void)viewDidLoad: {
NSLog(@"%d", self.view.frame.size.width);
}
будет печатать неправильные размеры во многих случаях (в частности, он сильно разбит в ландшафтном режиме)
Это приведет к возврату всегда скорректированных результатов, поэтому неплохо разместить макеты субвью:
- (void)viewWillAppear: {
NSLog(@"%d", self.view.frame.size.width);
}
Проблема заключается в том, что viewWillAppears вызывается каждый раз, когда появляется представление, поэтому он не подходит для размещения или добавления subviews. Таким образом, вы в конечном итоге объявляете каждый вид в интерфейсе, и в итоге вы получаете огромные файлы заголовков, которые мне совсем не нравятся, поскольку большинству элементов больше не нужны манипуляции после начальной настройки.
Итак, первый вопрос: Есть ли лучший способ для обработки позиционирования подпрограмм?
Вопрос два очень связан, скажем, у меня есть подкласс UIView, включая различные другие подпункты. Я объявляю его внутри своего интерфейса, и я выделяю/инициализирую его в методе init/viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
...
menu = [[SNKSlidingMenu alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
...
}
Как мы уже знаем, теперь нам нужно переместить его в viewWillAppear, чтобы получить более точное чтение
- (void)viewWillAppear:(BOOL)animated{
....
menu.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
....
}
Проблема заключается в том, что, конечно, все подсмотры также необходимо переместить. Это выполняется с помощью функции layoutSubviews, которая вызывается автоматически, но у нас есть та же проблема: Все подзапросы должны быть объявлены внутри интерфейса класса SNKSlidingMenu. Есть ли способ обойти это?
Спасибо.
Ответы
Ответ 1
Если вы настроите iOS 5.0 или лучше, вы можете использовать viewWillLayoutSubviews
и viewDidLayoutSubviews
для внесения изменений.
Что касается вашего второго вопроса, если вам нужен доступ к переменной экземпляра в другом методе, чем init
, вам нужно сохранить его, я не вижу проблемы с ним.
Однако вы можете использовать автоматические макеты и настраивать правила между подзонами, чтобы они автоматически выкладывались для вас без необходимости сохранять ссылку.
Ответ 2
viewDidLoad
вызывается только при создании вашего представления, но многие вещи могут повлиять на размер frame
, и он не будет вызван снова, когда изменяется frame
.
Вместо
- создать подпрограммы в
viewDidLoad
- установить их размеры в
viewWillLayoutSubviews
.
См. дополнительную информацию для обработки вращения: fooobar.com/questions/164519/...
Ответ 3
viewWillLayoutSubviews
и viewDidLayoutSubviews
могут решить эту проблему.
Но два methed будут выполняться больше раз.
это мой код, чтобы получить правильный self.view.frame
.
- (void)viewDidLoad {
[super viewDidLoad];
...
dispatch_async(dispatch_get_main_queue(), ^{
// init you view and set it`s frame. this can get correct frame.
...
}
...
}
Ответ 4
Это спасло мою жизнь не раз:
override func viewDidLoad() {
super.viewDidLoad()
self.view.setNeedsLayout()
self.view.layoutIfNeeded()
}
В основном это заставляет viewcontroller правильно расположить его представление, и оттуда вы можете получить правильные кадры для всех ваших подпредставлений. Это особенно помогает при анимации переходов, а ваши контроллеры представления используют autolayout и построитель интерфейса.
Из того, что я заметил, похоже, что начальные кадры установлены в соответствии с тем, какой класс размера по умолчанию установлен в вашем конструкторе интерфейсов. Я обычно редактирую, используя класс размера iPhone XS, поэтому в viewDidLoad кажется, что ширина просмотра всегда равна 375 независимо от того, используете ли вы iPhone XR или нет. Это исправляет себя перед viewWillAppear, хотя.
Приведенный выше код исправит эту проблему и позволит вам получить правильные кадры для вашего представления/подпредставления до того, как ViewController будет отображен на экране.