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

Каков процесс рождения UIViewController (какой метод следует)?

Существует много способов переопределить, например initWithNibname:, awakeFromNib, loadView, viewDidLoad, viewDidAppear:, layoutSubviews, и я просто не могу решить, в каком порядке этот метод называется.

Я просто переопределяю одну из них "наизусть".

Любое подробное объяснение?

4b9b3361

Ответ 1

Сценарий " Cocoa происходит с кучей за кулисами.

1. Объект viewController

В самом базовом, viewController является общим объектом контроллера. Когда он сначала выделяется инициализированным, он не имеет связанного с ним объекта вида. Представление создается только тогда, когда (и если) требуется. Таким образом, без учета представления жизненный цикл viewController совпадает с любым другим объектом:

UIViewController * myVC = [[UIViewController alloc] initWith...];
...
[myVC release];

Назначенный инициализатор для viewControllers -initWithNibname:bundle:. Если вы указываете наконечник, viewController может автоматически загрузить свой вид из этого nib и подключить любые IBOutlets, которые вы определили (см. Ниже для более подробной информации).

2. Загрузка и выгрузка вида

Функция viewController будет загружать свое представление по мере необходимости. Обычно это происходит, когда метод -view вызывается в первый раз и может произойти в любое время в вашей программе, в зависимости от того, как вы инициализируете свой пользовательский интерфейс. Просмотр также может быть уничтожен и перезагружен несколько раз в течение всего срока действия вашей программы, агана в зависимости от того, как вы управляете своим пользовательским интерфейсом. Когда viewController определил, что его представление требуется, но еще не загружено, будет вызван метод -loadView. Основной поток сообщений выглядит примерно так:

view
  loadView
  viewDidLoad

Обратите внимание, что если вы переопределите метод -view, -loadView и viewDidLoad не будут вызываться автоматически. Если вы переопределите -loadView, вы должны установить свойство viewController view. В противном случае следующий вызов -view снова вызовет процесс загрузки.

Вид можно также выгрузить в любое время в течение жизни вашей программы, просто установив для свойства view значение nil. Реализация по умолчанию -didReceiveMemoryWarning по умолчанию будет выполняться автоматически, если в представлении нет супервизора (т.е. Если в настоящее время он не является частью иерархии активного представления). Поток сообщений выглядит следующим образом:

view = nil
   viewDidUnload

2a. Загрузка программного обеспечения программно

Если вы решите переопределить -loadView, вы можете создать представление, subviews, другие viewControllers и любые соединения между этими объектами любым способом. Конечно, это означает, что вы также отвечаете за управление памятью в отношении создаваемых объектов. Если ваш подкласс переопределяет -loadView, он должен быть инициализирован с использованием nil для nibName и bundle.

2b. Загрузка изображения из низа

Если вы используете файл nib, реализация по умолчанию -loadView автоматически откроет этот файл nib, создаст экземпляр его объектов, добавит любые соединения между ними и позаботится о вашем управлении памятью.

Все становится немного сложнее с файлами nib, так как так происходит за кулисами. Метод -awakeFromNib вызывается для каждого объекта, который создается при загрузке файла nib, и нет гарантии, что другие объекты в файле nib будут полностью загружены при его вызове.

3. Отображение просмотров

-viewWillAppear:, -viewDidAppear:, -viewWillDisappear: и -viewDidDisappear: вызывается только тогда, когда представление отображается или скрывается на экране, особенно во время анимированных переходов из одного представления в другое. Эти методы могут быть вызваны много раз в течение жизни вашей программы, так как представления меняются местами и выходят в вашей схеме навигации.

4. Макет вида

Метод -layoutSubviews не является частью UIViewController. Он вызывается для объектов UIView, когда их границы были изменены. Если вы используете пользовательский подкласс UIView в вашей программе, этот метод можно использовать для создания настраиваемого макета subview вместо того, чтобы полагаться на Cocoa методы автосохранения по умолчанию.

5. Объединяя все это

Из-за сложности существует много разных способов для этого процесса, но нормальная временная шкала может выглядеть примерно так:

-[viewController initWithNibname:Bundle:]
-[viewController awakeFromNib]
-[viewController loadView]
-[view awakeFromNib]
-[viewController viewDidLoad]
-[viewController viewWillAppear]
-[viewController viewDidAppear]
...
-[viewController viewWillDisappear]  // user navigated away
-[viewController viewDidDisappear]
...
-[viewController viewWillAppear]     // user navigated back
-[viewController viewDidAppear]
...
-[viewController viewWillDisappear]  // user navigated away
-[viewController viewDidDisappear]
...
-[viewController setView:nil]        // memory warning, perhaps
-[viewController viewDidUnload]
...
-[viewController loadView]           // user navigated back
-[view awakeFromNib]
-[viewController viewDidLoad]
-[viewController viewWillAppear]
-[viewController viewDidAppear]
...

Ответ 2

В последнее время я снова просмотрел и создал тестовый проект: https://github.com/Janek2004/ViewControllerTest

Запустите проект на симуляторе iOS, чтобы увидеть порядок выполнения подкласса UIViewController. Заказ может отличаться, если мы используем Nib файл вместо программ раскадровки или контроллера просмотра.

  • - [ViewController initWithCoder:] Удаление данных из nib или раскадровки
  • - [ViewController awakeFromNib] Подготавливает ресивер к сервису после его загрузки из архива интерфейса Builder или nib файл.
  • - [ViewController loadView] Вы никогда не должны вызывать этот метод напрямую. Контроллер вида вызывает этот метод, когда его вид свойство запрашивается, но в настоящее время оно равно нулю. Этот метод загружает или создает представление и присваивает его свойству вида.
  • - [ViewController viewDidLoad] Этот метод вызывается после того, как контроллер представления загрузил свою иерархию представлений в память.
  • - [ViewController viewWillAppear:] Этот метод вызывается до того, как представление получателей будет добавлено в иерархию представления и до любые анимации настроены для отображения представления.
  • - [ViewController viewWillLayoutSubviews] Вызывается, чтобы уведомить контроллер представления о том, что его представление предназначено для компоновки его подпрограмм. Когда изменения представлений изменяются, представление регулирует положение его подзонов. Контроллер просмотра может переопределить этот метод, чтобы внести изменения до вид излагает свои подходы.
  • - [ViewController viewDidLayoutSubviews] Вызывается, чтобы уведомить контроллер представления о том, что его представление только что выложило его подпункты. Когда изменение границ для представления контроллеров вида, представление регулирует позиции его подзонов, а затем система вызывает этот метод. Однако этот метод, который вызывается, не указывает, что индивидуальные макеты представлений представлений были скорректированы. каждый subview отвечает за настройку собственного макета.
  • - [ViewController viewDidAppear:] Уведомляет контроллер представления о том, что его представление было добавлено в иерархию представления. Вы можете переопределить этот метод для выполнения дополнительных задач, связанных с представлением представления.

  • - [ViewController viewWillDisappear:] Уведомляет контроллер представления о том, что его представление будет удалено из иерархии представлений. Это метод вызывается в ответ на представление, удаляемое из представления иерархия. Этот метод вызывается до фактического удаления представления и перед настройкой любых анимаций. Уведомляет о представлении чтобы его представление было добавлено в иерархию представлений. Ты можешь переопределить этот метод для выполнения дополнительных задач, связанных с представляя представление.

  • - [ViewController viewDidDisappear:] Уведомляет контроллер вида, что его вид был удален из иерархии представлений.

Ответ 3

Еще один ключевой момент в этом процессе - когда layoutSubviews вызывается в любых подзаголовках. Именно в этот момент, а не раньше, были применены любые ограничения, настроенные в раскадровке. Если вам нужно внести какие-либо корректировки в подпункты представления, основанные на ограниченных координатах, вы должны сделать это в layoutSubviews. Если вы сделаете это в viewDidLayoutSubviews, это будет слишком рано, так как эти подзаголовки еще не применяли свои ограничения (потому что в документации говорится: "Каждое подчинение отвечает за настройку собственного макета".) И если вы сделаете это в viewDidAppear, это будет слишком поздно, так как пользователь увидит, что ваши подзоны меняют координаты. Итак, другой важный шаг в этом процессе:

-viewController viewWillAppear
-viewController viewWillLayoutSubviews
-viewController viewDidLayoutSubviews
---> viewController.[any subview] layoutSubviews
-viewController viewDidAppear  

Ответ 4

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

Когда вы определяете новый подкласс UIViewController, вы должны указать виды, которыми должен управлять контроллер. Существует два взаимоисключающих способа указать эти представления: вручную или с помощью файла nib. Если вы укажете представления вручную, вы должны реализовать метод loadView и использовать его для назначения объекту корневого представления для свойства view. Если вы укажете представления с помощью файла nib, вы не должны переопределять loadView, но вместо этого должны создать файл nib в Interface Builder, а затем инициализировать объект контроллера View с помощью метода initWithNibName: bundle:. Создание представлений с использованием файла nib часто проще, потому что вы можете использовать приложение Interface Builder для создания и настройки ваших представлений графически (в отличие от программно). Однако оба метода имеют одинаковую конечную цель, которая заключается в создании соответствующего набора представлений и их экспонирования через свойство вида.

С головы:

  • initWithNibname
  • loadView (загрузка вручную)
  • viewDidiLoad
  • viewDidAppear

нет подсказки, где layoutSubviews входит

Ответ 5

Обычно я решаю этот вопрос, помещая NSLog (или контрольные точки) во всех этих делегатах, включая делегат запуска приложения, и следуя порядку в отладчике.

Ответ 6

-- This is related to view only:
-viewWillAppear:
-viewDidAppear: 
-viewWillDisappear: and 
-viewDidDisappear: 

are only called when the view is being displayed.

-viewController viewDidLoad
-viewController viewWillAppear
-viewController viewDidAppear

other methods

-viewController viewDidDisappear
-viewController viewWillDisappear 
-viewController viewDidUnload

Ответ 7

Я хочу поблагодарить e.James за его отличное описание. Я еще не могу прокомментировать сообщение, но для быстрой визуальной иллюстрации см. эту блок-схему в руководстве по программированию View Controller. И я понимаю, что это не по теме, но для графика последовательности запуска приложения см. Руководство по программированию приложений iOS.