Как View Controller Containment работает в iOS 5?
На WWDC 2011 Session 102 компания Apple представила View Controller Containment, которая представляет собой возможность создавать пользовательские контейнеры контроллера представления, аналогичные UITabBarController
, UINavigationController
, и тому подобное.
Я смотрел примеры несколько раз. Есть множество методов, связанных с этим шаблоном, но было немного сложно точно их выяснить. Я собираюсь опубликовать здесь то, что я думаю, и посмотреть, подтвердит ли сообщество или не подтвердит мои подозрения.
Сценарий 1: переход от родительского элемента управления к новому родительскому контроллеру представления
[vc willMoveToParentViewController:self];
[self addChildViewController:vc];
[self.view addSubview:vc.view]; // or something like this.
[vc didMoveToParentViewController:self];
Должны ли первые две строки располагаться в указанном порядке, или они могут быть обращены?
Сценарий 2. Переход от родительского контроллера представления к родительскому контроллеру представления
[vc willMoveToParentViewController:nil];
[vc.view removeFromSuperview];
[vc removeFromParentViewController];
Также необходимо позвонить [vc didMoveToParentViewController:nil]
? Примеры в Сессии 102 не делали этого в этом сценарии, но я не знаю, было ли это упущением или нет.
Сценарий 3: Переход от одного родительского контроллера представления к другому
Вероятно, это произойдет следующим образом, поскольку логика в каждом родительском контроллере представления будет инкапсулирована.
// In the old parent
[vc willMoveToParentViewController:nil];
[vc.view removeFromSuperview];
[vc removeFromParentViewController];
// In the new parent
[vc willMoveToParentViewController:self];
[self addChildViewController:vc];
[self.view addSubview:vc.view];
[vc didMoveToParentViewController:self];
Вопросы
Мой главный вопрос заключается в следующем: должно ли это вообще работать в контроллере представления? Механика, приведенная выше, верна?
Нужно ли звонить willMoveToParentViewController
перед звонком addChildViewController
? Это кажется мне логичным порядком, но действительно ли это необходимо?
Нужно ли звонить didMoveToParentViewController:nil
после звонка removeFromParentViewController
?
2 ответа
UIViewController
Документы достаточно ясно, когда и когда не звонить willMove
/ didMove
методы. Ознакомьтесь с документацией "Реализация контроллера представления контейнера".
Документы говорят, что если вы не переопределите addChildViewController
Вам не нужно звонить willMoveToParentViewController:
метод. Однако вам нужно позвонить didMoveToParentViewController:
Метод после завершения перехода. "Кроме того, контроллер представления контейнера отвечает за вызов willMoveToParentViewController:
метод перед вызовом removeFromParentViewController
метод. removeFromParentViewController
метод вызывает didMoveToParentViewController:
метод дочернего контроллера представления. "
Также здесь есть разработанный пример и пример кода.
Удачи
Эта часть не верна:
[vc willMoveToParentViewController:self];
[self addChildViewController:vc];
[self.view addSubview:vc.view]; // or something like this.
[vc didMoveToParentViewController:self];
Когда ваш пользовательский контейнер вызывает метод addChildViewController:, он автоматически вызывает willMoveToParentViewController: метод контроллера представления, который будет добавлен как дочерний элемент перед его добавлением.
Так что вам не нужно [vc willMoveToParentViewController:self]
вызов. Это делается автоматически, когда вы звоните [self addChildViewController:vc]
, Вот пример кода снова:
[self addChildViewController:vc];
// [vc willMoveToParentViewController:self] called automatically
[self.view addSubview:vc.view]; // or something like this.
[vc didMoveToParentViewController:self];
Для удаления контроллеров представления:
Метод removeFromParentViewController автоматически вызывает didMoveToParentViewController: метод дочернего контроллера представления после того, как он удаляет дочерний элемент.
Предположительно этот звонок [oldVC didMoveToParentViewController:nil]
,
[vc willMoveToParentViewController:nil];
[vc.view removeFromSuperview];
[vc removeFromParentViewController];
// [vc didMoveToParentViewController:nil] called automatically