Я злоупотребляю UIViewController Subclassing? - PullRequest
31 голосов
/ 17 апреля 2011

Пытаясь выяснить, почему 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.

В этом случае UIViewController должен находиться только непосредственно в Window или UINavigationController, UITabBarController и т. Д.?

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

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

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

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

1 Ответ

38 голосов
/ 17 апреля 2011

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

Так что, в принципе, либо я совершенно не прав, либо я в погоне за диким гусем.

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

  • Представление - это, конечно, любой объект, который является экземпляром UIView или подклассом UIView.
  • ВВ контексте MVC «представление» используется коллективно, и мы говорим о том или ином, что является «обязанностью представления», даже если «представление» действительно является группой объектов.
  • Когда мы говорим о контроллере представления,«представление», которым управляет контроллер, - это экземпляр 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, ваши собственные контейнеры теперь могут отображать представлениянескольких дочерних контроллеров представления.Написание контроллера представления контейнера является довольно сложной темой - вы должны быть хорошо знакомы с использованием контроллеров представления в целом и с тем, как работают предоставленные контроллеры представления контейнера, прежде чем попытаться создать свой собственный.

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