Massive View Controller - IOS - Solutions

16

Jestem pewien, że każdy nowy programista iOS ma następujący problem: kontrolery widoków bardzo szybko zapełniają się kodem do różnych celów, łatwo przechodząc do ponad 500 linii kodu.

Tak to wygląda dla dwóch podstawowych i typowych ekranów:

1) Ekran formularza: wprowadź opis zdjęcia tutaj

2) Ekran kontrolera widoku tabeli wprowadź opis zdjęcia tutaj

Do tej pory przeczytałem o dwóch różnych rozwiązaniach:

  1. Pierwsze rozwiązanie: https://bendyworks.com/single-responsibility-principle-ios/ . Jest to oparte na powiadomieniach, całkowicie oddziela kontroler widoku od modelu widoku (intencje), a tym samym zmniejsza kod w kontrolerze widoku. Myślę, że ma wadę łamania kodu, podobną do struktur Go-To. To wygląda tak: wprowadź opis zdjęcia tutaj

  2. Drugie rozwiązanie utrzymuje te same zatłoczone kontrolery widoku (akcje przycisków są wykonywane wewnątrz VC i tak dalej). ale korzysta z bibliotek takich jak TPKeyboardAvoiding , BlocksKit lub innych rozwiązań, w większości opartych na kategoriach. Dzięki temu drugiemu rozwiązaniu kod jest drastycznie zredukowany, ale kontroler widoku nadal ponosi dużą odpowiedzialność.

Co sądzisz o tych rozwiązaniach? Który jest lepszy? Czy jest lepszy?

Ravul
źródło
5
Z powodu czasu nie mogę udzielić dobrej odpowiedzi, ale powinno to wskazać właściwy kierunek.
Mike D,
Moim zamiarem jest zebranie jak największej liczby dobrych odpowiedzi, aby w końcu pokonać ten problem, który ma tak wielu nowych programistów. Dzięki za link, jeśli znajdę coś nowego, z pewnością opublikuję go tutaj.
Ravul
Oto świetna rozmowa o walce z grubymi kontrolerami widoku autorstwa Andy'ego Matuschaka https://realm.io/news/andy-matuschak-refactor-mega-controller/
Tomasz Bąk

Odpowiedzi:

6

Możemy użyć MVVM do rozwiązania tego problemu.

Wzorzec Model-View-ViewModel lub wzorzec MVVM, jak to jest powszechnie znane, to wzorzec projektowy interfejsu użytkownika. VM bierze całą logikę na temat przygotowywania danych modelu dla interfejsu użytkownika z VC.

Przykład:
Masz obiekt modelu z niektórymi polami, chcesz sformatować niektóre z nich, dokonać obliczeń i połączyć je.

W przypadku MVC cała ta logika znajduje się w ViewController.
W MVVM przenosisz wszystko z VC na VM.

VM przygotuje wszystkie dane do interfejsu użytkownika, a VC tak to po prostu ustawia.

(w klasie VC)

self.descriptionLabel = self.viewModel.textForDescriptionLabel;

Samouczki i tematy:

kaspartus
źródło
3
Chociaż teoretycznie może to odpowiedzieć na pytanie, lepiej byłoby zawrzeć tutaj istotne części odpowiedzi i podać odnośnik.
Bart van Ingen Schenau,
Zgadzam się z Bartem. Jeśli nikt inny nie opublikuje podsumowania wszystkich tych metod, zrobię je, gdy tylko je zrozumiem i przetestuję.
Ravul,
2
@Ravul zaktualizowana odpowiedź
kaspartus,
Podniosłem głos twojej odpowiedzi i dziękuję za ten pomysł. Właśnie czytam o funkcyjnym programowaniu reaktywnym i wydaje się to dobrym pomysłem. Myślę, że odpowiedzią na to pytanie jest wyliczenie z kilkoma zaletami, wadami i co najmniej jednym schematem koncepcyjnym dla następujących 4 sposobów podejścia do problemu: 1) Reaktywne kakao 2) KVO 3) Metoda delegowania i 4) Klasyczny sposób pisanie kontrolera widoku. Napiszę to, jak tylko przetestuję wszystkie te metody, jeśli nikt inny nie zrobi tego przede mną. Jeśli w międzyczasie znajdę nowe sposoby, będzie jeszcze lepiej.
Ravul,
3

Wcześniej musiałem rozplątywać kod w dużych kontrolerach widoku, co na początku bardzo utrudniało mi nawigację. Zrozumiałem, że sam rozmiar kontrolera widoku nie był wystarczającym powodem, by coś rozdzielić. Złożenie 1 dużego pliku jest skomplikowane, a złożoność małych plików. Oto kilka ważnych powodów, aby zrefaktoryzować rozbicie kontrolera widoku na mniejsze części:

MVC

Kontroler widoku nie powinien robić nic więcej niż być klejem łączącym widok z modelem. Jeśli masz dużo kodu połączenia sieciowego, kodu manipulacji obrazem itp., Zastanów się nad podzieleniem ich na klasy pomocnicze.

Wiele elementów sterujących za pomocą kontrolera widoku jako źródła danych

Jeśli masz kilka kontrolek na ekranie, które mają Twój kontroler widoku jako źródło danych, rozważ podzielenie ich na osobne obiekty źródła danych i niech będą źródłem danych. Możesz też podzielić je na osobne kontrolery widoku (tak jak jeśli widok kontrolera ma widok tabeli oprócz innego kontrolera, możesz podzielić go na własną klasę kontrolera widoku tabeli).

Duplikat kodu

Jeśli masz dokładnie ten sam kod w różnych kontrolerach widoku, umieść go w 1 wspólnej lokalizacji. To sprawi, że kod będzie wielokrotnego użytku i pomoże zarządzać złożonością.

Oto kilka dodatkowych porad, aby zminimalizować złożoność kontrolera widoku:

Storyboard zamiast Programmatic

Tworzenie elementów widoku to dużo kodu, a kod geometrii ramki również wymaga dużo pracy. Jeśli nie, rozważ użycie automatycznych ograniczeń układu i umieszczenie jak największej liczby elementów widoku w serii ujęć.

Niepotrzebny kod / komentarze

Pamiętaj też o usunięciu niepotrzebnego kodu / komentarzy. Wiele razy nowy plik kontrolera widoku zawiera metody, których nie używasz. Jeśli nie używasz takiej metody, możesz didReceiveMemoryWarningją bezpiecznie wyjąć. Ponadto, ponieważ plik kontrolera widoku jest tak duży, że czasami trudno jest usunąć stary kod lub komentarze. Nie odkładaj tego! To tylko zwiększa złożoność.

Powiadomienia

Aby odpowiedzieć na twoje pytanie dotyczące powiadomień: Powiadomienia nie są Złotym Młotem do użycia we wszystkim. Uważam, że powiadomienia są przydatne, gdy wiele kontrolerów widoku wymaga aktualizacji w tym samym czasie z powodu 1 określonej akcji. Uważaj jednak na powiadomienia, ich nadużywanie może sprawić wiele bólu podczas próby ich wyśledzenia.

Korey Hinton
źródło
2

Istnieje jedna specjalna architektura, którą nazywają VIPER (View, Interactor, Presenter, Entity and Routing). Spróbuję tu wznowić to, co musisz wiedzieć:

Widok

  • są to atrapy poglądów;
  • zawierają obiekty takie jak UIView, UIViewController, UILabel itp;
  • czeka na treść od Prezentera ;
  • obsłużyć interakcję użytkownika i przekazać ją do warstwy Presenter .

Prezenter

  • nie zna obiektów interfejsu użytkownika;
  • uzyskać dane wejściowe z warstwy Widok ;
  • obsłużyć logikę widoku (metoda add wyświetli inny ekran);

Wytyczanie

  • obsługiwać logikę nawigacji i animacje przejścia;
  • zna obiekty takie jak UINavigationController, UIWindow itp;

Więc, co myślę, że wyczyścisz w swoim kodzie:

  • sprawdzanie poprawności danych zostanie przeniesione do warstwy Presenter ;

  • nawigacja zostanie przeniesiona do obiektów szkieletowych ( warstwa trasy );

  • podziel swój kontroler widoku, przestrzegając zasady OSUSZANIA ;

  • Złożone ekrany będą miały dwa lub więcej widoków i prezenterów.

Powinieneś zobaczyć poniższy link o architekturze VIPER http://mutualmobile.github.io/blog/2013/12/04/viper-introduction/

Powodzenia!

orafaelreis
źródło
1
Czy ta architektura działa w przypadku małych aplikacji? Wygląda na to, że musisz stworzyć wiele obiektów, aby wprowadzić go do projektu.
Tomasz Bąk
tak, zgadzam się, że jest bardziej obiektowy niż tradycyjny MVC, ale jest wart. Możesz zobaczyć jeden prosty przykład, który stworzyłem w tym roku github.com/orafaelreis/cascavel Cascavel jest jak projekt podstawowy do inicjowania projektów VIPER.
orafaelreis
Doskonały ! Architektura VIPER wydaje się być zaprojektowana właśnie w celu uniknięcia problemu masowych kontrolerów widoku.
Christophe