Правильная реализация loadView - PullRequest
14 голосов
/ 21 марта 2012

В документах Apple не указано, какая правильная реализация для loadView.

Я обнаружил, что если вы реализуете loadView следующим образом:

- (void)loadView
{
    self.view = [[UIView alloc] init];
}

... тогда вы получите другоеповедение, чем если вы не реализуете его вообще.В частности, в одном 20-строчном проекте я обнаружил, что viewWillAppear вызывается с фреймом нулевого размера для self.view - если только вы не используете версию loadView от Apple по умолчанию.

Глядя на Google, естьмножество «учебных пособий», которые предоставляют явно неправильные реализации loadView - например, принудительно установив размер (320,480), потому что автор учебника «обнаружил, что это работает, если я делаю это».

Я хотел бы знатькакова должна быть правильная реализация.

NB: в моем примере выше я добавляю его в иерархию представлений внутри AppDelegate следующим образом:

[self.window addSubview:(UIViewController*).view];

Я считаю, что при наличииUINavigationController или UITabBarController, Apple делает некоторую дополнительную магию, которая - как побочный эффект - заставляет реализацию loadView в одну строку работать нормально.Но я хочу написать это правильно, чтобы оно всегда работало!

Примечание: я пытался установить маску автоматического изменения размера в корневом представлении, но это не меняет того, что происходит:

- (void)loadView
{
    self.view = [[UIView alloc] init];
    self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}

Ответы [ 2 ]

15 голосов
/ 27 февраля 2013

Реализация по умолчанию -loadView создает представление или загружает NIB .Насколько я знаю, нет никакого способа узнать окончательный размер представления во время создания в -loadView.Таким образом, размер представления по умолчанию установлен на UIScreen.mainScreen.bounds.Это потому, что может быть трудно работать с нулевым просмотром кадра в -viewDidLoad и других методах.

Ваша однострочная реализация может выглядеть так:

- (void)loadView {
    self.view = [[UIView alloc] initWithFrame:UIScreen.mainScreen.bounds];
}

Вы не делаетенужно установить маску авторазмера, потому что вы не знаете, в каком контексте будет отображаться представление.Вызывающий абонент должен установить правильный кадр, маску авторазмера и аналогичные свойства.

Представьте себе это в методе UINavigationController:

// we are pushing new VC, view is accessed for the first time
pushedVC.view.frame = CGRectMake(...);

Он устанавливает правильный кадр, но ваш -loadView называется просто до , что -setFrame:.Таким образом, во время -viewDidLoad у вас есть временный ненулевой кадр, просто чтобы иметь возможность настроить подпредставления и внутреннее авторазмер.После этого вам будет задан правильный кадр, и в -viewWillAppear: у вас будет последний кадр.

13 голосов
/ 21 марта 2012

Во-первых, не существует реализации по умолчанию loadView ... этот метод специально для вас, чтобы переопределить.Я согласен, что документы Apple могут быть немного неясными, хотя.Но loadView вызывается по умолчанию всякий раз, когда к представлению контроллера навигации обращаются, и представление не существует (например: UIView *view = viewController.view).Его также можно вызвать вручную.Но ни в одной ситуации loadView не будет иметь правильных размеров ... что на самом деле невозможно.loadView вызывается для того, чтобы родительский контроллер представления получил представление в первую очередь, чтобы он мог соответствующим образом изменить его размер.Затем, как только он получает представление, он вызывает viewDidLoad.Это единственный путь кода, который они могут использовать, потому что представления могут загружаться из метода loadView или пера, и они должны предоставлять место для дополнительной настройки, когда представления загружаются из пера.Наконец, родительский контроллер изменит размер представления и вызовет viewWillAppear только тогда, когда представление действительно появится.Например, если вы поместите контроллер на navController, который находится за пределами экрана, он не будет вызывать viewWillAppear, пока сам navController не появится на экране.Это сделано потому, что нет смысла запускать этот код, пока контроллер не станет видимым.По этой же причине вы можете получить правильный размер только в методе viewWillAppear.

Теперь вы заметили, что если вы добавляете контроллер к стандартному контроллеру, ничего такого не происходит.Это связано с тем, что контроллеры представления на самом деле не должны содержать других контроллеров представления.Теперь в iOS 5 они явно поддерживают использование Контейнеров Контроллера Представления ... который по существу является контроллером представления, который разработан, чтобы содержать другие контроллеры представления.Они добавили несколько удобных методов в iOS 5, чтобы помочь с этим, но это не является строго необходимым.Суть всего этого такова: если вы хотите добавить один контроллер представления в другой, вам придется вручную настроить все соответствующие вызовы дочернего контроллера представления (все методы загрузки, события вращения, предупреждение о памяти и т. Д.).Другими словами, вы должны сделать свой собственный контроллер представления контейнера.Однако, когда вы это сделаете, помните, что я говорил ранее о пути кода.Важно, чтобы вы вызывали дочерние методы контроллера в том же порядке, что и Apple, иначе все будет работать неправильно.

Вот несколько ссылок на информацию: http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html - Прокрутите вниз до: Реализация контроллера представления контейнера.

Также здесь для жизненного цикла контроллера представления, который поможет вам выяснить, какие вызовы должны быть сделаны в каком порядке: http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/ViewLoadingandUnloading/ViewLoadingandUnloading.html#//apple_ref/doc/uid/TP40007457-CH10-SW1

Я рекомендую прочитать полное Руководство по программированию View Controller.... оттуда вы можете получить много информации: http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/Introduction/Introduction.html#//apple_ref/doc/uid/TP40007457-CH1-SW1

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...