Я злоупотребляю подклассом UIViewController?

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

В соответствии со следующим сообщением viewWillAppear не запускается при использовании addSubView! и ссылки на это сообщение в блоге: http://blog.carbonfive.com/2011/03/09/abusing-uiviewcontrollers/ Подклассы UIViewController должны выполняться только в очень специфических ситуациях. Наиболее заметно, когда они добавляются непосредственно в UIWindow или другие пользовательские контроллеры Apple, такие как UINavigationControllers.

Я, конечно, виноват в добавлении представлений подклассов UIViewController к представлениям других подклассов UIViewController.

На самом деле, я думал, что это была более или менее полная идея реализации Apple MVC в целом... Один общий VC, с другими VC внизу, все с радостью получили свои методы делегирования.

Если в приложении, представленном в этой статье, есть много представлений (которые по определению нуждаются в контроле), и множество экранов, каждая модель должна иметь один главный подкласс VC, со всеми подзонами вместо этого управляются пользовательскими контроллерами (которые управляют представлениями), которые являются подклассами простого NSObject.

В этом случае UIViewControllers должен быть только непосредственно в Window или UINavigationController, UITabBarController и т.д.?

Вы гарантированно получаете в этом случае методы делегатов UIVC? Как это отличается от вызова методов делегата вручную, когда представление viewcontroller является подчиненным другим VC?

Честно говоря, это кажется огромной тратой времени. Пользовательские реализации ViewDidLoad, viewDidLoad, viewDidUnload, viewWillAppear, viewWillDisappear, не говоря уже о таких простых вещах, как свойства, например, "просмотр"...

Так что, в принципе, я был совершенно неправ, или я нахожусь на дикой гусиной погоне. Если подклассы UIViewController не могут рассчитывать на вызов viewWillAppear, почему бы просто не вызвать этот метод вручную и не сделать с ним?

Зачем копировать все воспринимаемые функции UIViewController?

Ответ 1

Ответ на вопрос заголовка: Да.

Итак, в основном, я был совершенно неправильно, или я одинок гусиная погоня.

Похоже, вы были совершенно неправы. Термин "вид" имеет несколько разных, но связанных значений:

  • Конечно же, просмотр - это любой объект, являющийся экземпляром UIView или подкласса UIView.
  • В контексте MVC "view" используется совместно, и мы говорим о том, что тот или иной "воспринимаем ответственность", хотя "представление" действительно представляет собой группу объектов.
  • Когда речь идет о контроллере представления, "просмотр", которым управляет контроллер, является экземпляром UIView, который в представлении контроллера указывает на и иерархию подъявлений, которые он содержит.

Похоже, ваше непонимание в этом последнем пункте. Контроллер представления должен управлять одним "экранным" контентом. Если вы используете один объект контроллера представления для управления несколькими иерархиями представлений или используете несколько контроллеров представлений для управления разными частями одной и той же иерархии представлений, вы используете UIViewController таким образом, который никогда не был предназначен и что может привести к проблемам.

Используемые вами методы (-viewDidLoad, -viewWillAppear и т.д.) предназначены для указания контроллеру представления, что его иерархия представлений только что загружена, вот-вот будет отображаться и так далее. Они действительно не предназначены для обозначения отдельного поднабора, и для диспетчера представлений было бы необычно требоваться предоставить эту информацию для отдельных подзонов. Если иерархия представления была загружена, контроллер представления знает, что все в этой иерархии загружено.

Вы, кажется, интерпретируете эти методы как методы делегирования, но это не так. Делегат - это отдельный объект, который позволяет настраивать делегата без необходимости подкласса. -viewDidLoad и -viewWillAppear - два примера переопределения точек для UIViewController, класса, предназначенного для подкласса. Объект контроллера вида вызывает эти методы сам, чтобы дать подклассам возможность предпринять некоторые действия в интересной точке жизненного цикла контроллера.

Если подклассы UIViewController не могут рассчитывать на вызов viewWillAppear, почему бы просто не назвать этот метод вручную и выполняться с ним?

Взгляните на UIViewController, и вы увидите, что большая часть предоставленных функций связана с отображением вида ( то есть иерархию представлений) на экране или с интегрированием контроллера с контроллерами вида "контейнер", такими как UINavigationController и UITabBarController. Ничто из этого не полезно для объектов, которые не управляют всем экраном содержимого.

Иногда бывает, что группа представлений будет реплицироваться на нескольких экранах, и в некоторых из этих случаев полезно управлять этими представлениями с помощью объекта, который отделен от самого контроллера представления. Я вижу, как у вас возникнет соблазн использовать UIViewController из-за его -viewDidLoad и подобных методов, но это действительно лишь малая часть того, что делает UIViewController. Что это значит называть -presentModalViewController: на одном из этих объектов? Или получить доступ к своим свойствам navigationController или parentViewController?

Если вы действительно хотите управлять подзонами иерархии представления вашего контроллера представления с помощью этих методов, создайте подкласс NSObject, который имеет методы -viewDid [Load | Unload | Appear | Disappear] и -viewWill [Appear | Disappear]. Вы можете создать этот класс один раз, а затем подклассировать его так часто, как вам нужно, и ни один из ваших "подконтрольных" классов не будет иметь все лишнее, ненужное управление контроллером, которое поставляется вместе с UIViewController.

Изменить: Я хочу добавить указатель сюда в Руководство по программированию Apple View Controller для iOS, которое обеспечивает большая поддержка того, что я изложил выше. Здесь соответствующий отрывок из подраздела под названием "Просмотр контроллеров для управления иерархией представлений":

Просмотр контроллеров напрямую связанный с одним объектом вида но этот объект часто является просто корнем представление гораздо большей иерархии представлений что также управляется представлением контроллер. Контроллер представления действует в качестве центрального координационного агента для иерархия представлений, обработка обменов между его взглядами и любыми соответствующими контроллером или объектами данных. Один контроллер просмотра обычно управляет виды, связанные с одним экранов, а в Приложения для iPad это не всегда в этом случае.

Просмотреть инструкцию по программированию контроллера чтения требуется для тех, кто даже думает о написании приложения iOS. Стоит пересмотреть, если вы не прочитали его через какое-то время (или когда-либо).

Обновление: Начиная с iOS 5, теперь можно определить свои собственные контроллеры представления контейнеров, то есть просматривать контроллеры, которые управляют другими контроллерами представлений, и потенциально одновременно отображать представления нескольких контроллеров представлений. Подробнее об этом вы можете прочитать в руководстве, приведенном выше в разделе Создание пользовательских контроллеров просмотра контейнеров. Ничто из этого не изменит основные моменты выше: один контроллер представления должен по-прежнему управлять иерархией представлений, а методы типа -viewDidLoad по-прежнему относятся ко всему графику представления, а не к отдельным подзонам. Совет, который контроллер просмотра управляет "полным экранным" контентом, больше не является полностью точным - так же, как UISplitViewController отобразил контент с двух контроллеров представлений одновременно с момента внедрения iPad, ваши собственные контейнеры теперь могут отображать представления из нескольких контроллеров детского просмотра. Написание контроллера контейнера представляет собой несколько продвинутую тему - вы должны хорошо знать использование контроллеров представлений в целом и способ работы контроллеров представления контейнеров, прежде чем вы начнете создавать свои собственные.