L'uso di un controller di visualizzazione non intrinsecamente viola l'SRP. È davvero facile farlo perché su iOS sono l'elemento più importante nell'architettura nominalmente MVC. Ciò che appare in una vista e in un modello sembra ovvio; sono stupidi Quindi tutto ciò che ti rimane è Controller. Hai un controller (View) perché è richiesto dal sistema, e se non stai pensando, devi solo inserire tutte le cose lì.
Il codice di esempio di Apple non presenta grandi caratteristiche architettoniche perché è stato scritto per dimostrare una piccola parte delle funzionalità del framework, non come un progetto per un'app. Apple non vuole vuoi per progettare male la tua app; hanno solo altre priorità. Anche alcuni buoni libri su iOS ignorano in gran parte le linee guida di progettazione come la separazione delle preoccupazioni al fine di presentare succintamente informazioni sul sistema.
È certamente possibile definire una singola responsabilità per un controller di visualizzazione: media tra la sua vista e i dati rappresentati dalla vista. (Vedi anche: MVC: il controllore infrange il principio di responsabilità singola? ) Ciò significa che ha due attività: interpretare input dalla vista e per configurare la vista per la visualizzazione. Qualsiasi cosa oltre quei passaggi dovrebbe essere avviata il più rapidamente possibile ad altri oggetti.
Ad esempio, la vista riceve un tocco in una particolare sottoview. La vista indica al controller e il controller interpreta quel messaggio come a rappresentare il desiderio dell'utente di scaricare un'immagine. Ora il controller di visualizzazione deve instradare immediatamente la richiesta dell'utente a un componente "downloader", che è effettivamente responsabile di tale azione. Il controller della vista potrebbe anche dover riconfigurare la vista, oppure attendere che qualcosa ritorni dal suo oggetto helper per primo.
In entrambi i casi, il controller della vista non sta facendo altro che la traduzione tra la sua vista e altre parti dell'app. Questo dovrebbe essere al massimo un paio di righe.
Il problema che ti preoccupa è ben noto ai tecnici ingegnosi di iOS: è noto come "Massive View Controller" (come decollo di "Model View Controller"). Soroush Khanlou ha alcuni articoli davvero eccellenti su come evitare la trappola .
In iOS, i due principali schemi per evitare la sindrome di Massive View Controller sono chiamati MVVM e VIPER.
Sotto MVVM - probabilmente meglio descritto in un articolo su objc.io - il visualizza controller e vista sono considerati una singola unità. Un modello di vista separato contiene la "logica di presentazione": i dettagli su come trasformare i dati grezzi dal modello nelle informazioni necessarie alla vista. È ancora il controller che configura la vista, però.
Come esempio concreto, il modello potrebbe avere un "livello di allerta": solo un valore grezzo. Il modello di vista lo tradurrà in una stringa che descrive l'avviso e un colore. Il controller della vista prende la stringa e la inserisce nell'etichetta appropriata e applica il colore a un particolare elemento della vista. Non sa come sono stati calcolati la corda e il colore, o da dove provengono, o quanto spesso cambieranno, e non gli interessa. Tutto ciò che fa sa è dove metterli. Ogni logica è ha è strettamente orientata alla vista: se eseguire un'animazione, quale dovrebbe essere la costante di un vincolo.
L' architettura a cinque componenti di VIPER viene anche presentata a objc.io . Anche in questo caso, il controller di visualizzazione è considerato parte della vista, ma molte delle responsabilità che potrebbero essere associate a MVC generico sono ora suddivise in altri due oggetti: Interactator e Presenter.
L'Interactor risponde all'input dell'utente per manipolare i dati del modello. Presenter è simile al modello di visualizzazione sopra: trasforma i dati del modello in attributi di visualizzazione. (In MVVM, il modello di vista avrebbe fatto entrambe le cose.)
Il punto chiave per il dimming del controller in VIPER, a mio avviso, è il "Router", a volte chiamato "Wireframe". È essenzialmente responsabile della transizione tra le viste . Questo richiede molto del potenziale di complessità e responsabilità extra da parte dei controllori della vista; * non devono più capire cosa verrà dopo quando il loro compito è terminato. Anche se non vuoi adottare rigorosamente VIPER, suggerirei vivamente di esaminare questa idea.
* In un certo senso usare segues risolve anche questo, ma i segues arrivano con problemi di flessibilità. In particolare, sei costretto a utilizzare initWithCoder:
invece di essere in grado di creare inizializzatori personalizzati per i tuoi controller di visualizzazione.