Interfacce utente iOS: storyboard vs NIB vs codice personalizzato
Pubblicato: 2022-03-11Sento spesso che gli sviluppatori iOS fanno qualche variante della stessa domanda chiave:
Qual è il modo migliore per sviluppare un'interfaccia utente in iOS: tramite Storyboard, NIB o codice?
Le risposte a questa domanda, in modo esplicito o implicito, tendono a presupporre che ci sia una scelta mutuamente esclusiva da fare, che spesso viene affrontata in anticipo, prima dello sviluppo.
Sono del parere che la risposta debba invece assumere la forma di una o più controdomande .
Qual è l'auto "migliore"?
Mi spiego con un esempio fuori tema. Dì che voglio comprare un'auto e ti faccio una semplice domanda: "Qual è la scelta migliore?"
Puoi davvero rispondere suggerendo un modello, o anche una marca? Non è probabile, a meno che tu non suggerisca una Ferrari. Invece, probabilmente risponderesti con alcune altre domande, come:
- Qual è il tuo budget?
- Di quanti posti hai bisogno?
- Ti interessa il consumo di carburante?
- Cosa ne pensi delle auto sportive?
È ovvio che non esiste un'auto buona o cattiva a meno che non sia inserita in un contesto adeguato: c'è solo un'auto buona o cattiva in base a esigenze specifiche.
Torna a Progettazione interfaccia utente iOS
Proprio come con la nostra richiesta di auto, la domanda "Qual è il modo migliore per sviluppare un'interfaccia utente iOS" manca di contesto. E abbastanza sorprendentemente, la risposta non deve essere un caso generale.
In generale, ci sono tre tipi di approcci alla progettazione dell'interfaccia utente che puoi adottare, ognuno con i suoi pro e contro, i suoi fan e odiatori:
- Storyboard iOS : uno strumento visivo per il layout di più visualizzazioni di applicazioni e le transizioni tra di esse.
- NIB (o XIB) : ogni file NIB corrisponde a un singolo elemento di visualizzazione e può essere disposto in Interface Builder, rendendolo anche uno strumento visivo. Si noti che il nome "NIB" deriva dall'estensione del file (in precedenza .nib e ora .xib, sebbene la vecchia pronuncia sia rimasta).
- Codice personalizzato : cioè, nessuno strumento GUI, ma piuttosto, gestire tutto il posizionamento personalizzato, l'animazione, ecc. a livello di codice.
Nessuna di queste opzioni è universalmente migliore di qualsiasi altra (nonostante ciò che potresti sentire).
Gli storyboard, ad esempio, sono l'ultima aggiunta al toolkit dell'interfaccia utente di iOS. Mi è stato detto che sono il futuro, che sostituiranno i NIB e le UI con codice personalizzato. Vedo Storyboards come uno strumento utile, ma non tanto un sostituto quanto un complemento per NIB e codice personalizzato. Gli storyboard sono la scelta giusta in alcune, ma non in tutte le situazioni.
Inoltre, perché dovresti restare staticamente su una singola opzione quando puoi usarle tutte (nello stesso progetto), scegliendo il meccanismo che meglio si adatta al problema specifico a portata di mano?
Questa è una domanda che, a mio avviso, può essere generalizzata a un livello superiore e la cui risposta è ai primi posti nel mio elenco di principi di sviluppo software: non esiste un linguaggio, un framework o una tecnologia universali che sia la scelta universale migliore per ogni problema di sviluppo del software. Lo stesso vale per la progettazione dell'interfaccia utente iOS.
In questo tutorial sullo sviluppo di iOS, esploreremo ciascuno di questi metodi e introdurremo casi d'uso in cui dovrebbero e non dovrebbero essere impiegati, nonché modi in cui possono essere combinati insieme.
Storyboard iOS
Un classico errore da principiante è creare un enorme Storyboard iOS a livello di progetto. Anche io ho commesso questo errore quando ho iniziato a lavorare con gli Storyboard (probabilmente perché è una strada allettante da prendere).
Come suggerisce il nome, uno Storyboard è una tavola con una storia da raccontare . Non dovrebbe essere usato per mescolare storie non correlate in un unico grande volume. Uno storyboard dovrebbe contenere controller di visualizzazione logicamente correlati tra loro, il che non significa ogni controller di visualizzazione.
Ad esempio, ha senso utilizzare Storyboard durante la gestione di:
- Un insieme di viste per l'autenticazione e la registrazione.
- Un flusso di immissione degli ordini in più fasi.
- Un flusso simile a una procedura guidata (cioè un tutorial).
- Un insieme di viste master-dettaglio (ad es. elenchi di profili, dettagli di profilo).
Nel frattempo, gli storyboard di grandi dimensioni dovrebbero essere evitati, inclusi gli storyboard singoli a livello di app (a meno che l'app non sia relativamente semplice). Prima di andare più a fondo, vediamo perché.
La follia dei grandi storyboard iOS
Gli storyboard di grandi dimensioni, oltre a essere difficili da sfogliare e mantenere, aggiungono un livello di complessità all'ambiente di un team: quando più sviluppatori lavorano contemporaneamente sullo stesso file di storyboard, i conflitti di controllo del codice sorgente sono inevitabili . E mentre uno storyboard è rappresentato internamente come un file di testo (un file XML, in realtà), l'unione di solito non è banale.
Quando gli sviluppatori visualizzano il codice sorgente, gli attribuiscono un significato semantico. Quindi, quando si uniscono manualmente, sono in grado di leggere e comprendere entrambi i lati di un conflitto e agire di conseguenza. Uno storyboard, invece, è un file XML gestito da Xcode, e il significato di ogni riga di codice non è sempre di facile comprensione.
Facciamo un esempio molto semplice: supponiamo che due sviluppatori diversi modifichino la posizione di una UILabel
(usando il layout automatico), e quest'ultimo spinga la sua modifica, producendo un conflitto come questo (notare gli attributi id
in conflitto):
<layoutGuides> <viewControllerLayoutGuide type="top"/> <viewControllerLayoutGuide type="bottom"/> </layoutGuides> <layoutGuides> <viewControllerLayoutGuide type="top"/> <viewControllerLayoutGuide type="bottom"/> </layoutGuides>
L' id
stesso non fornisce alcuna indicazione sul suo vero significato, quindi non hai nulla con cui lavorare. L'unica soluzione significativa è scegliere una delle due parti del conflitto e scartare l'altra. Ci saranno effetti collaterali? Chissà? Non tu.
Per risolvere questi problemi di progettazione dell'interfaccia iOS, l'utilizzo di più storyboard nello stesso progetto è l'approccio consigliato.
Quando usare gli storyboard
Gli storyboard vengono utilizzati al meglio con più controller di visualizzazione interconnessi, poiché la loro principale semplificazione risiede nella transizione tra i controller di visualizzazione. In una certa misura, possono essere pensati come una composizione di NIB con flussi visivi e funzionali tra i controller di visualizzazione.
Oltre a facilitare il flusso di navigazione, un altro vantaggio distinto è che eliminano il codice standard necessario per visualizzare, spingere, presentare e chiudere i controller di visualizzazione. Inoltre, i controller di visualizzazione vengono allocati automaticamente, quindi non è necessario alloc
e init
manualmente.
Infine, mentre gli storyboard sono utilizzati al meglio per scenari che coinvolgono più controller di visualizzazione, è anche difendibile utilizzare uno Storyboard quando si lavora con un singolo controller di visualizzazione tabella per tre motivi:
- La possibilità di progettare prototipi di celle di tabella sul posto aiuta a tenere insieme i pezzi.
- È possibile progettare più modelli di celle all'interno del controller di visualizzazione della tabella padre.
- È possibile creare viste di tabelle statiche (un'aggiunta tanto attesa che purtroppo è disponibile solo negli Storyboard).
Si potrebbe sostenere che più modelli di celle possono anche essere progettati utilizzando NIB. In verità, questa è solo una questione di preferenza: alcuni sviluppatori preferiscono avere tutto in un posto, mentre altri non si preoccupano.
Quando non usare gli storyboard iOS
Alcuni casi:
- La vista ha un layout complicato o dinamico, implementato al meglio con il codice.
- La vista è già implementata con NIB o codice.
In questi casi, possiamo lasciare la vista fuori dallo Storyboard o incorporarla in un controller di visualizzazione. Il primo interrompe il flusso visivo dello Storyboard, ma non ha implicazioni funzionali o di sviluppo negative. Quest'ultimo mantiene questo flusso visivo, ma richiede sforzi di sviluppo aggiuntivi poiché la vista non è integrata nel controller della vista: è semplicemente incorporata come componente, quindi il controller della vista deve interagire con la vista anziché implementarla.
Pro e contro generali
Ora che abbiamo un'idea di quando gli storyboard sono utili nella progettazione dell'interfaccia utente iOS e prima di passare ai NIB in questo tutorial, esaminiamo i loro vantaggi e svantaggi generali.
Pro: prestazioni
Intuitivamente, puoi presumere che quando uno Storyboard viene caricato, tutti i suoi controller di visualizzazione vengono istanziati immediatamente. Fortunatamente, questa è solo un'astrazione e non è vera per l'implementazione effettiva: viene invece creato solo il controller di visualizzazione iniziale, se presente. Gli altri controller di visualizzazione vengono istanziati dinamicamente, quando viene eseguito un passaggio o manualmente dal codice.
Pro: prototipi
Gli storyboard semplificano la prototipazione e la simulazione delle interfacce utente e del flusso. In realtà, un'applicazione prototipo funzionante completa con viste e navigazione può essere facilmente implementata utilizzando Storyboard e poche righe di codice.
Contro: Riutilizzabilità
Quando si tratta di spostare o copiare, gli storyboard iOS sono mal posizionati. Uno Storyboard deve essere spostato insieme a tutti i suoi controller di visualizzazione dipendenti. In altre parole, un controller di visualizzazione singolo non può essere estratto individualmente e riutilizzato altrove come un'unica entità indipendente; dipende dal resto dello Storyboard per funzionare.
Contro: flusso di dati
I dati spesso devono essere passati tra i controller di visualizzazione durante la transizione di un'app. Tuttavia, il flusso visivo dello Storyboard è interrotto in questo caso poiché non c'è traccia di ciò che accade in Interface Builder. Gli storyboard si occupano della gestione del flusso tra i controller di visualizzazione, ma non del flusso di dati. Quindi, il controller di destinazione deve essere configurato con il codice, sovrascrivendo l'esperienza visiva.
In questi casi, dobbiamo fare affidamento su un prepareForSegue:sender
, con uno scheletro if/else-if come questo:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { NSString *identifier = [segue identifier]; if ([identifier isEqualToString@"segue_name_1"]) { MyViewController *vc = (MyViewController *) [segue destinationViewController]; [vc setData:myData]; } else if ([identifier isEqualToString@"segue_name_2"]) { ... } else if ... }
Trovo che questo approccio sia soggetto a errori e inutilmente dettagliato.
NIB
I NIB sono il vecchio modo per eseguire la progettazione dell'interfaccia iOS.
In questo caso, "vecchio" non significa "cattivo", "obsoleto" o "deprecato". In effetti, è importante capire che gli storyboard iOS non sono un sostituto universale per i NIB; in alcuni casi semplificano semplicemente l'implementazione dell'interfaccia utente.
Con i NIB, è possibile progettare qualsiasi vista arbitraria, che lo sviluppatore può quindi allegare a un controller di visualizzazione secondo necessità.
Se applichiamo la progettazione orientata agli oggetti alle nostre interfacce utente, ha senso suddividere la vista di un controller di visualizzazione in moduli separati , ciascuno implementato come vista con il proprio file NIB (o con più moduli raggruppati nello stesso file). Il chiaro vantaggio di questo approccio è che ogni componente è più facile da sviluppare, più facile da testare e più facile da eseguire il debug.

I NIB condividono i problemi di conflitto di unione che abbiamo riscontrato con gli Storyboard, ma in misura minore, poiché i file NIB operano su scala ridotta.
Quando utilizzare i NIB per la progettazione dell'interfaccia utente iOS
Un sottoinsieme di tutti i casi d'uso sarebbe:
- Viste modali
- Accesso semplice e visualizzazioni di registrazione
- Impostazioni
- Finestre a comparsa
- Modelli di visualizzazione riutilizzabili
- Modelli di celle di tabella riutilizzabili
Nel frattempo…
Quando non usare i pennini
Dovresti evitare di usare i NIB per:
- Viste con contenuto dinamico, in cui il layout cambia in modo significativo a seconda del contenuto.
- Viste che per natura non sono facilmente progettabili in Interface Builder.
- Visualizza i controller con transizioni complicate che potrebbero essere semplificate con Storyboarding.
Pro e contro generali
Più in generale, esaminiamo i pro ei contro dell'utilizzo dei NIB.
Pro: riutilizzabilità
I NIB sono utili quando lo stesso layout è condiviso tra più classi.
Come semplice caso d'uso, un modello di visualizzazione contenente un nome utente e un campo di testo password potrebbe essere implementato con le ipotetiche TTLoginView
e TTSignupView
, che potrebbero provenire entrambe dallo stesso NIB. TTLoginView
dovrebbe nascondere il campo della password ed entrambi dovrebbero specificare le etichette statiche corrispondenti (come "Inserisci il tuo nome utente" vs "Inserisci la tua password"), ma le etichette avrebbero la stessa funzionalità di base e layout simili.
Pro e contro: prestazioni
I NIB vengono caricati pigramente, quindi non usano la memoria finché non è necessario. Anche se questo può essere un vantaggio, c'è latenza nel processo di caricamento lento, il che lo rende anche un aspetto negativo.
Codice personalizzato iOS (interfaccia utente programmatica)
Qualsiasi progetto di interfaccia iOS che può essere fatto con Storyboard e NIB può anche essere implementato con codice grezzo (c'è stato un tempo, ovviamente, in cui gli sviluppatori non avevano il lusso di un insieme così ricco di strumenti).
Forse ancora più importante, ciò che non può essere fatto con NIB e Storyboard può sempre essere implementato con il codice, a condizione, ovviamente, che sia tecnicamente fattibile. Un altro modo di vedere è che i NIB e gli Storyboard sono implementati con il codice, quindi la loro funzionalità sarà naturalmente un sottoinsieme. Passiamo subito ai pro e ai contro.
Pro: Sotto il cofano
Il più grande vantaggio di creare un'interfaccia utente iOS a livello di codice: se sai come codificare un'interfaccia utente, allora sai cosa succede sotto il cofano , mentre lo stesso non vale necessariamente per NIB e Storyboard.
Per fare un confronto: una calcolatrice è uno strumento utile. Ma non è una brutta cosa sapere come eseguire i calcoli manualmente.
Questo non è limitato a iOS, ma a qualsiasi strumento RAD visivo (ad esempio, Visual Studio e Delphi, solo per citarne alcuni). Gli ambienti Visual HTML RAD rappresentano un tipico caso limite: vengono utilizzati per generare codice (spesso scritto male), sostenendo che non è necessaria alcuna conoscenza dell'HTML e che tutto può essere fatto visivamente. Ma nessuno sviluppatore web implementerebbe una pagina web senza sporcarsi le mani: sanno che la gestione manuale del codice HTML e CSS grezzo porterà a un codice più modulare ed efficiente.
Quindi, padroneggiare la codifica delle interfacce utente iOS ti dà un maggiore controllo e una maggiore consapevolezza di come questi pezzi si incastrano, il che aumenta il tuo limite come sviluppatore.
Pro: quando il codice è l'unica opzione
Ci sono anche casi in cui il codice iOS personalizzato è l'unica opzione per la progettazione dell'interfaccia utente. I layout dinamici, in cui gli elementi della vista vengono spostati e il flusso o il layout si adattano in modo significativo in base al contenuto, sono esempi tipici.
Pro: unisci conflitti
Mentre NIB e Storyboard hanno sofferto in modo significativo di conflitti di unione, il codice non ha lo stesso difetto. Tutto il codice ha un significato semantico, quindi risolvere i conflitti non è più difficile del solito.
Contro: Prototipazione
È difficile capire come apparirà un layout finché non lo vedi in azione. Inoltre, non è possibile posizionare visivamente viste e controlli, quindi la traduzione delle specifiche di layout in una vista tangibile può richiedere molto più tempo, rispetto a NIB e Storyboard che offrono un'anteprima immediata di come verranno visualizzate le cose.
Contro: Refactoring
Anche il refactoring del codice che è stato scritto molto tempo fa o da qualcun altro diventa molto più complicato: quando gli elementi vengono posizionati e animati con metodi personalizzati e numeri magici, le sessioni di debug possono diventare ardue.
Pro: prestazioni
In termini di prestazioni, Storyboard e NIB sono soggetti al sovraccarico di caricamento e analisi; e alla fine, vengono indirettamente tradotti in codice. Inutile dire che questo non accade con le interfacce utente create da codice.
Pro: riutilizzabilità
Qualsiasi vista implementata a livello di codice può essere progettata in modo riutilizzabile. Vediamo alcuni casi d'uso:
- Due o più viste condividono un comportamento comune, ma sono leggermente diverse. Una classe base e due sottoclassi risolvono il problema in modo elegante.
- Un progetto deve essere biforcato, con l'obiettivo di creare un'unica base di codice, ma generare due (o più) diverse applicazioni, ognuna con personalizzazioni specifiche.
Lo stesso processo di progettazione dell'interfaccia utente sarebbe molto più complicato con NIB e Storyboard. I file modello non consentono l'ereditarietà e le possibili soluzioni sono limitate a quanto segue:
- Duplica i file NIB e Storyboard. Dopodiché, hanno vite separate e nessuna relazione con il file originale.
- Sovrascrivi l'aspetto e il comportamento con il codice, che può funzionare in casi semplici, ma può portare a complicazioni significative in altri. Override pesanti con il codice possono anche rendere inutile la progettazione visiva ed evolvere in una fonte costante di mal di testa, ad esempio, quando un determinato controllo viene visualizzato in un modo in Interface Builder, ma ha un aspetto completamente diverso quando l'app è in esecuzione.
Quando usare il codice
È spesso una buona scelta utilizzare il codice personalizzato per la progettazione dell'interfaccia utente iOS quando si dispone di:
- Layout dinamici.
- Viste con effetti, come angoli arrotondati, ombre, ecc.
- Qualsiasi caso in cui l'utilizzo di NIB e Storyboard sia complicato o irrealizzabile.
Quando non utilizzare il codice
In generale, è sempre possibile utilizzare le UI create dal codice. Raramente sono una cattiva idea, quindi metterei un
Sebbene NIB e Storyboard apportino alcuni vantaggi al tavolo, ritengo che non ci sia alcun aspetto negativo ragionevole che inserirei in un elenco per scoraggiare l'utilizzo del codice (tranne, forse, la pigrizia).
Un progetto, più strumenti
Storyboard, NIB e codice sono tre diversi strumenti per la creazione dell'interfaccia utente iOS. Siamo fortunati ad averli. I fanatici delle UI programmatiche probabilmente non terranno conto delle altre due opzioni: il codice ti consente di fare tutto ciò che è tecnicamente possibile, mentre le alternative hanno i loro limiti. Per il resto degli sviluppatori là fuori, il coltellino Xcode fornisce tre strumenti che possono essere utilizzati tutti in una volta, nello stesso progetto, in modo efficace.
Come, chiedi? Come ti piace. Ecco alcuni possibili approcci:
- Raggruppa tutte le schermate correlate in gruppi separati e implementa ogni gruppo con il proprio Storyboard distinto.
- Progetta celle di tabella non riutilizzabili sul posto con uno Storyboard, all'interno del controller di visualizzazione tabella.
- Progetta celle di tabella riutilizzabili nei NIB per incoraggiare il riutilizzo ed evitare la ripetizione, ma carica questi NIB tramite codice personalizzato.
- Progetta viste, controlli e oggetti intermedi personalizzati utilizzando i NIB.
- Utilizzare il codice per visualizzazioni altamente dinamiche e, più in generale, per visualizzazioni non facilmente implementabili tramite Storyboard e NIB, mentre alloggiano le transizioni di visualizzazione in uno Storyboard.
Per chiudere, diamo un'occhiata a un ultimo esempio che lega tutto insieme.
Un semplice caso d'uso
Supponiamo di voler sviluppare un'app di messaggistica di base con diverse visualizzazioni:
- Un elenco di amici seguiti (con un modello di cella riutilizzabile per mantenere l'interfaccia utente coerente negli elenchi futuri).
- Una vista dettagliata del profilo, composta in sezioni separate (incluse informazioni sul profilo, statistiche e una barra degli strumenti).
- Un elenco di messaggi inviati e ricevuti da un amico.
- Un nuovo modulo per i messaggi.
- Una visualizzazione cloud di tag che mostra i diversi tag utilizzati nei messaggi dell'utente, con ogni tag di dimensioni proporzionali al numero di volte in cui è stato utilizzato.
Inoltre, vogliamo che le visualizzazioni scorrano come segue:
- Facendo clic su un elemento nell'elenco degli amici seguiti vengono visualizzati i dettagli del profilo dell'amico pertinente.
- I dettagli del profilo mostrano il nome del profilo, l'indirizzo, le statistiche, un breve elenco dei messaggi più recenti e una barra degli strumenti.
Per implementare questa app iOS, tutti e tre i nostri strumenti dell'interfaccia utente torneranno utili, poiché possiamo usare:
- Uno Storyboard con quattro controller di visualizzazione (l'elenco, i dettagli, l'elenco dei messaggi e il nuovo modulo dei messaggi).
- Un file NIB separato per il modello di cella dell'elenco dei profili riutilizzabile.
- Tre file NIB separati per la visualizzazione dei dettagli del profilo, uno per ciascuna delle sezioni separate che lo compongono (dettagli del profilo, statistiche, ultimi tre messaggi), per consentire una migliore manutenibilità. Questi NIB verranno istanziati come viste e quindi aggiunti al controller di visualizzazione.
- Codice personalizzato per la visualizzazione tag cloud. Questa vista è un tipico esempio di una che non può essere progettata in Interface Builder, né tramite StoryBoard né NIB. Invece, è completamente implementato tramite codice. Per mantenere il flusso visivo dello Storyboard, scegliamo di aggiungere un controller di visualizzazione vuoto allo Storyboard, implementare la visualizzazione del tag cloud come visualizzazione autonoma e aggiungere a livello di codice la visualizzazione al controller di visualizzazione. Chiaramente, la vista potrebbe essere implementata anche all'interno del controller della vista piuttosto che come vista standalone, ma le teniamo separate per un migliore riutilizzo.
Un mock-up davvero semplice potrebbe essere simile a:
Con ciò, abbiamo delineato la costruzione di base di un'app iOS ragionevolmente sofisticata le cui viste principali legano i nostri tre approcci principali alla progettazione dell'interfaccia utente. Ricorda: non è necessario prendere una decisione binaria, poiché ogni strumento ha i suoi punti di forza e di debolezza.
Avvolgendo
Come esaminato in questo tutorial, gli Storyboard aggiungono una notevole semplificazione al design dell'interfaccia utente di iOS e al flusso visivo. Eliminano anche il codice boilerplate; ma tutto questo ha un prezzo, pagato in flessibilità. I NIB, nel frattempo, offrono maggiore flessibilità concentrandosi su un'unica vista, ma senza flusso visivo. La soluzione più flessibile, ovviamente, è il codice, che tende ad essere piuttosto ostile e intrinsecamente non visivo.
Se questo articolo ti ha incuriosito, ti consiglio vivamente di guardare il grande dibattito di Ray Wenderlich, 55 minuti ben spesi per una discussione su NIB, Storyboard e UIS code-made.
In chiusura, voglio sottolineare una cosa: evitare a tutti i costi di utilizzare lo strumento di progettazione dell'interfaccia utente iOS improprio . Se una vista non è progettabile con uno Storyboard o se può essere implementata con NIB o codice in un modo più semplice, non utilizzare uno Storyboard. Allo stesso modo, se una vista non è progettabile utilizzando NIB, non utilizzare NIB. Queste regole, sebbene semplici, faranno molto nella tua formazione come sviluppatore.