5

Mam UIViewController - nazwijmy go "FormController" - który jest po prostu formą, która edytuje obiekt. Chcę używać go w 2 różnych sytuacjach:Ponowne użycie UIViewController w sytuacjach modalnych i niemodalnych

  1. Tworzenie nowego obiektu - przy użyciu przy użyciu metody UINavigationController za presentModalViewController:.

  2. Edytowanie istniejącego obiektu - przesuń kontroler widoku na stos UINavigationController, nie używając metody okna dialogowego.

Istnieje niewielka różnica, że ​​w modalnej sytuacji chciałbym mieć pasek narzędzi z „Anuluj” i „Gotowe” przycisków, natomiast w sytuacji stosu Chciałbym tylko mieć pasek nawigacyjny pod warunkiem przez UINavigationController.

Byłoby to podobne do aplikacji Kontakty, w której ekrany "Nowy kontakt" i ekran "Edytuj kontakt" używają tego samego kontrolera widoku, ale formularz Nowy kontakt jest prezentowany modalnie, podczas gdy ekran Edytuj jest przesyłany do nawigacji stos.

Moje pytanie brzmi: Jaki jest najlepszy sposób na radzenie sobie w obu sytuacjach bez konieczności pisania 2 osobnych, ale w większości identycznych kontrolerów widoku?

Pomyślałem o stworzeniu "ModalFormController", który hermetyzuje gołe "FormController" poprzez kompozycję i dodaje pasek narzędzi, ale czytałem gdzieś w dokumentach, że Apple nie zaleca zagnieżdżania kontrolerów widoku.

Odpowiedz

2

To, co robię (czasami), to ustawienie enum określające typ kontrolera widoku. Na przykład możesz mieć dwa typy: typ Edit i typ Add ("nowy").

Typ Add jest zaimplementowany za pomocą modalnego kontrolera widoku, natomiast typ Edit jest przesyłany na istniejący stos nawigacyjny.

W metodzie kontrolera widoku -viewDidLoad: po prostu robię drzewo switch/case, które ustawia tytuł i inne cechy wyglądu w zależności od wyszczególnienia typu określonego powyżej.

Zaletą jest to, że łatwo jest dodać nowy typ. Minusem jest to, że warunkowe drzewo do przekazania tego wyliczenia może szybko się skomplikować, w zależności od tego, jak różne są te typy.

Drzewo switch/case ułatwia zarządzanie.

To zależy od tego, co próbujesz zrobić z tymi dwoma typami. Ale jest to zdecydowanie wykonalne.

+2

Dzięki Alex. Myślę, że wszystkie odpowiedzi były poprawne, ale po pewnych rozważaniach zamierzam pójść w kierunku, który ustawiłeś. Po prostu użyję BOOL-a, który wie, czy FormController jest wyświetlany modalnie. – Sam

3

Dlaczego nie używać podklasy? Utwórz ModalCreateFormController podklasę o nazwie EditFormController i zajmij się obiektami specyficznymi dla modów w podklasie.

+0

Myślałem o tym też. Może spróbuję tego następnym razem ... Naprawdę ciężko mi było zdecydować, w którą stronę pójść. – Sam

2

Oprócz posiadania wyraźnego nieruchomości na kontrolerze widzenia (jak sugeruje Alex Reynolds), dwa inne podejścia, które przychodzą mi do głowy to:

  1. Jeśli masz jakiś model obiektowy, że jesteś edycji, poproś o jej aktualny stan. Jeśli kiedykolwiek został zapisany, jesteś w trybie edycji. W przeciwnym razie jesteś w trybie tworzenia.

  2. Sprawdź wartość właściwości kontrolera parentViewController. Jeśli jest to instancja UINavigationController, jesteś na stosie nawigacji. Jeśli wyświetlasz się modalnie, będzie to instancja kontrolera listy.

+0

Dzięki Sixten. Zamierzam użyć tego pomysłu w punkcie # 2 w połączeniu z odpowiedzią Alex powyżej. – Sam

0

musiałem to zrobić kilka razy w mojej aplikacji i po wypróbowaniu kilka różnych sposobów działania IT, łącznie modalnych podklasy & wielokrotnego użytku klas modalne pomocnicze, które wykorzystywane forwardInvocation. Znalazłem najlepszy wzorzec polegający na utworzeniu metody whichModalViewController dla każdego kontrolera widoku, który (zwykle) tworzy i zwraca UINavigationController dla wywołującego do użycia z presentModalViewController.

W większości przypadków ta metoda buduje i zwraca kontroler UINavigationController ze sobą jako kontrolerem widoku root (z wielokrotnymi wywołaniami metody sprawdzającej self.navigationController i zwracając go zamiast tego, jeśli nie jest zerowy). W innych przypadkach najpierw zrobiłem kontroler root i pchnąłem self na sekundę, aby uzyskać przycisk powrotu. Następnie można użyć triku, aby złapać przycisk Wstecz: http://smallduck.wordpress.com/2010/10/05/intercepting-uinavigationcontroller/

W niektórych przypadkach widok nie wymaga paska nawigacji, więc ta metoda tylko dostosowuje niektóre flagi i zwraca wartość "ja". Odkryłem nawet, że w niektórych przypadkach potrzebował paska nawigacyjnego, prostszą metodą było wywołanie self.view, a następnie dostrojenie hierarchii widoków w celu dodania UINavigationBar i ponownie powrotu do siebie. W każdym razie konfiguracja często jest izolowana do tej jednej metody, a wywołujący obsługuje ją w każdym przypadku.

1

Ug, nienawidzę dodatkowych Ivars ...

Używam tego zamiast:

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

     //Modal 

    }else{ 

     //Pushed 

    } 

Jest bit hack, ale używamy logikę, że jeśli kontroler widok wykraczająca jest pierwszym w stosie nie możesz wrócić. W rzeczywistości ignorujemy fakt, czy jest on w ogóle wyświetlany modalnie.

+1

tym, że okazało się do kategorii, UIViewController: - (Bool) isModal { \t zwrotny ([[self.navigationController viewControllers] objectAtIndex: 0] == siebie); } – marcelnijman

+0

@marcelnijman Chociaż rozumiem, co próbujesz zrobić z kategorią 'UIViewController', to nie działa we wszystkich przypadkach. Na przykład zwróci to fałszywy alarm dla początkowego kontrolera viewcontroller, ponieważ znajduje się on u góry stosu. – memmons