Повторное использование UIViewController для модальных и немодальных ситуаций - PullRequest
5 голосов
/ 31 октября 2009

У меня есть UIViewController - назовем его «FormController» - это просто форма, которая редактирует объект. Я хочу использовать его в 2 разных ситуациях:

  1. Создание нового объекта - с использованием метода presentModalViewController: UINavigationController.

  2. Редактирование существующего объекта - поместите контроллер представления в стек UINavigationController, не используя метод диалога.

Существует небольшая разница в том, что в модальной ситуации я хотел бы иметь панель инструментов с кнопками "Отмена" и "Готово", тогда как в ситуации со стеком я хотел бы просто иметь панель навигации, предоставляемую UINavigationController.

Это будет похоже на приложение «Контакты», в котором экраны «Новый контакт» и «Редактировать контакт», по-видимому, используют один и тот же контроллер представления, но форма «Новый контакт» представлена ​​модально, в то время как экран «Редактирование» помещается в стек навигации .

Мой вопрос: каков наилучший способ справиться с обеими ситуациями без необходимости писать 2 отдельных, но в основном идентичных контроллера представления?

Я думал о создании «ModalFormController», который инкапсулирует пустой «FormController» посредством композиции и добавляет панель инструментов, но где-то в документах я читал, что Apple не рекомендует вложения контроллеров представления.

Ответы [ 6 ]

3 голосов
/ 31 октября 2009

Почему бы не использовать подклассы? Сделайте ModalCreateFormController подклассом EditFormController и обработайте модальные вещи в подклассе.

2 голосов
/ 31 октября 2009

В дополнение к явному свойству на контроллере представления (как предполагает Алекс Рейнольдс), мне встречаются два других подхода:

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

  2. Посмотрите на значение свойства parentViewController контроллера. Если это экземпляр UINavigationController, значит, вы в стеке навигации. Если вы отображаетесь модально, это будет экземпляр вашего контроллера списков.

2 голосов
/ 31 октября 2009

То, что я делаю (иногда), настроено enum, которое определяет тип контроллера представления.

Например, у вас может быть два типа: тип Edit и тип Add («новый»).

Тип Add реализован через модальный контроллер вида, а тип Edit помещается в существующий стек навигации.

В методе -viewDidLoad: контроллера представления я просто создаю дерево switch/case, которое устанавливает заголовок и другие характеристики внешнего вида в зависимости от перечисления типов, указанного выше.

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

Но дерево switch/case значительно облегчает управление.

Итак, это зависит от того, что вы пытаетесь сделать с двумя типами. Но это определенно выполнимо.

1 голос
/ 12 октября 2011

Ug, я ненавижу лишние ивары ...

Я использую это вместо:

if([[self.navigationController viewControllers] objectAtIndex:0] == self){

        //Modal

    }else{

        //Pushed

    }

Это что-то вроде хака, но мы используем логику, что если контроллер представления, который нарушает работу, является первым в стеке, вы не можете вернуться назад. На самом деле мы игнорируем тот факт, отображается ли он модально вообще.

0 голосов
/ 28 сентября 2013

Apple объясняет, как приложение контактов работает под капотом:

Чтобы разрешить использовать пользовательский класс контроллера представления для отображения и редактирования содержимого, переопределите метод setEditing:animated:.

Вы получаете некоторые функции бесплатно, например, Edit/Done кнопка.

0 голосов
/ 06 марта 2011

Мне приходилось делать это несколько раз в моем приложении, и после того, как я попробовал несколько разных способов сделать это, включая модальные подклассы и повторно используемые классы модальных помощников, которые использовали forwardInvocation. Я обнаружил, что лучше всего было создать метод содержащийModalViewController для каждого контроллера представления, который (обычно) создает и возвращает UINavigationController для вызывающей стороны для использования с presentModalViewController.

В большинстве случаев этот метод создает и возвращает UINavigationController с self в качестве корневого контроллера представления (с повторными вызовами метода, проверяющего self.navigationController и возвращающим его вместо этого, если он не равен nil). В других случаях я сначала сделал фиктивный корневой контроллер и нажал себя на втором, чтобы получить кнопку возврата. Затем можно использовать трюк, чтобы поймать нажатие кнопки «назад»: http://smallduck.wordpress.com/2010/10/05/intercepting-uinavigationcontroller/

В некоторых случаях представление не нуждается в панели навигации, поэтому этот метод просто настраивает некоторые флаги и возвращает self. Я даже обнаружил, что в некоторых случаях нужна навигационная панель, было проще сделать так, чтобы этот метод вызывал self.view, затем настраивал иерархию представления, чтобы добавить UINavigationBar и снова возвращал self. Но в любом случае установка часто изолируется от этого одного метода, и вызывающая сторона обрабатывает его одинаково в каждом случае.

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