Lavorare con Table View Controller Swift
Scritto da Reinder de Vries, il 3 agosto 2020 in Sviluppo App per iOS
In questo tutorial vi mostrerò passo per passo come table view controller di lavoro, e come si possono utilizzare. Entreremo nell’intera gamma di UITableViewController
, immergendoci nella programmazione orientata agli oggetti, nella delega e nei meccanismi dietro le quinte delle viste da tavolo.
Un controller di visualizzazione tabella visualizza informazioni strutturate e ripetibili in un elenco verticale. Si utilizza la classe UITableViewController
nell’app iOS per creare un controller di visualizzazione tabella.
Lavorare con un controller di visualizzazione tabella significa anche lavorare con alcuni importanti concetti di sviluppo iOS, come la sottoclasse, il modello di progettazione della delega e il riutilizzo delle viste.
E ‘ importante per gli sviluppatori iOS professionali e pratici (voi!) per padroneggiare il lavoro con i controller di visualizzazione tabella. Una volta che ti sei abituato a lavorare su un componente UI così sfaccettato, come UITableViewController
, anche altri aspetti più complessi dello sviluppo di iOS inizieranno ad avere senso.
Pronto? Tuffiamoci!
- Come una Table View Controller Funziona
- impostare una Semplice Tabella View Controller
- La Codifica della Tabella Visualizza i Dati del Controller Source
- Fornitura di Celle di Tabella View Controller
- Risposta all’Interazione dell’Utente
- bibliografia
Come una Table View Controller Funziona
Se hai usato qualche app iOS prima, hai usato table view controller di prima. Sono usati frequentemente nelle app iOS!
Ecco un esempio di un controller di visualizzazione tabella:
Un controller vista tabella ha tipicamente questi componenti visibili:
- Una vista tabella, che è il componente dell’interfaccia utente, o vista, che viene visualizzato sullo schermo. Una vista tabella è un’istanza della classe
UITableView
, che è una sottoclasse diUIScrollView
. - Celle della vista tabella, che sono le righe o le viste ripetibili mostrate nella vista tabella. Una cella di visualizzazione tabella è un’istanza di una classe
UITableViewCell
e tale classe è spesso sottoclasse per creare celle di visualizzazione tabella personalizzate.
Un controller vista tabella si basa anche sull’uso di questi componenti, dietro le quinte:
- Un delegato della vista tabella, che è responsabile della gestione del layout della vista tabella e della risposta agli eventi di interazione dell’utente. Un delegato di visualizzazione tabella è un’istanza della classe
UITableViewDelegate
. - Origine dati vista tabella, responsabile della gestione dei dati in una vista tabella, incluse le celle e le sezioni della vista tabella. Un’origine dati è un’istanza della classe
UITableViewDataSource
.
Un controller di navigazione viene spesso utilizzato in combinazione con un controller di visualizzazione tabella per abilitare la navigazione tra la vista tabella e i controller di visualizzazione successivi e per mostrare una barra di navigazione sopra la vista tabella.
La parte più interessante del lavoro con i controller di visualizzazione tabella è il controller di visualizzazione tabella stesso! In che modo?
Hai familiarità con l’architettura Model-View-Controller? Secondo l’architettura Model-View-Controller, una vista tabella e una cella di visualizzazione tabella sono viste e un controller di visualizzazione tabella è un controller.
Le visualizzazioni sono responsabili della visualizzazione delle informazioni visibilmente all’utente, con un’interfaccia utente (UI). I controllori sono responsabili dell’implementazione della logica, della gestione dei dati e delle decisioni. Detto diversamente: non puoi vedere un controller, ma è lì, gestendo ciò che vedi attraverso le viste.
Quando si utilizza un controller di visualizzazione tabella nella propria app, si sottoclasse la classe UITableViewController
. La classe UITableViewController
stessa è una sottoclasse di UIViewController.
Ecco la gerarchia di classi di un controller di visualizzazione tabella di esempio che visualizza le informazioni di contatto:
- un’istanza di
ContactsTableViewController
- sottoclassi
UITableViewController
- sottoclassi
UIViewController
- sottoclassi
- sottoclassi
secondo i principi della Programmazione Orientata agli Oggetti (OOP), quando la classe RaceCar
sottoclassi della classe Vehicle
, eredita le proprietà e le funzioni della superclasse, come maxSpeed
e drive()
.
La classe Vehicle
viene quindi chiamata superclasse di RaceCar
. Questo principio è chiamato ereditarietà.
Confusione? Può essere! Pensaci così: affinché il tuo controller di visualizzazione tabella funzioni CORRETTAMENTE, dovrai ereditare un sacco di codice, quindi non devi scrivere tutto quel codice da solo. La gerarchia di classi e OOP sono lì per strutturare quell’ereditarietà.
È possibile lavorare con le viste tabella senza utilizzare un controller vista tabella. Basta aggiungere un UITableView
a un controller di visualizzazione, fornirgli le implementazioni del delegato della vista tabella e delle funzioni di origine dati e il gioco è fatto.
La classe UITableViewController
fornisce le implementazioni predefinite di queste funzioni di origine dati vista tabella e vista tabella. Questo è un aspetto cruciale del lavoro con un controller di visualizzazione tabella!
Come vedrai nei prossimi capitoli di questo tutorial, sostituiremo queste funzioni con le nostre implementazioni. Possiamo personalizzare il controller di visualizzazione tabella in questo modo.
Scopri come creare app iOS
Inizia con iOS 14 e Swift 5
Iscriviti al mio corso di sviluppo iOS e scopri come creare fantastiche app iOS 14 con Swift 5 e Xcode 12.
Impostazione di un semplice controller di visualizzazione tabella
Va bene, mettiamo tutto in pratica. In questa sezione, stiamo andando a costruire un semplice controller di visualizzazione tabella. Stai per implementare le funzioni necessarie per farlo funzionare, e ti spiegherò come funzionano mentre andiamo avanti. Diamoci una mossa!
È possibile utilizzare 3 diversi approcci per lavorare con Interfacce utente in Xcode:
- Creazione di viste a livello di programmazione, vale a dire la programmazione a mano
- Impostazione di Interfacce utente in Interface Builder e la loro connessione con il codice Swift via XIBs
- Impostazione di Interfacce utente e le loro transizioni in Interface Builder utilizza Storyboard
- (Tecnicamente, è possibile utilizzare SwiftUI troppo, ma come per table view controller, questo va oltre lo scopo di questo tutorial.)
È noioso e improduttivo codificare le UI a mano. Se non stai attento con gli Storyboard, finiscono per nascondere la complessità dallo sviluppatore. Stiamo andando a lavorare con Storyboard, mentre capire esattamente come funzionano dietro le quinte.
Ecco cosa farai:
Innanzitutto, crea un nuovo progetto Xcode tramite File → Nuovo → Progetto…. Assicurati di scegliere il modello di app e scegli Storyboard per l’interfaccia e Uikit App Delegato per il ciclo di vita.
Quindi, prendere questi passaggi:
- fare clic con il progetto in Project Navigator e scegliere Nuovo File…
- Scegliere il Cocoa Touch modello di Classe (iOS)
- Scegliere
UITableViewController
per Sottoclasse di - Nome della classe
ContactsTableViewController
- non spunta Anche creare file XIB
- Infine, fare clic su Avanti e salvare il file accanto all’altro Swift file
Infine, fare questo:
- Vai in
Main.storyboard
e rimuovere l’esistente View Controller Scena - Aggiungere una nuova Tabella Controller di Visualizzazione storyboard tramite la Libreria
- Con il table view controller selezionato, andare agli Attributi di Ispezione e selezionare l’È Vista Iniziale Controller casella di controllo
- Infine, andare per l’Identità di Ispezione e set di Classe a
ContactsTableViewController
ecco!!! Ora hai un controller di visualizzazione tabella all’interno dello storyboard del progetto e lo hai collegato alla classe Swift ContactsTableViewController
.
Come hai intuito, la tua classe ContactsTableViewController
è una sottoclasse di UITableViewController
. Puoi vederlo nel file Swift, in alto, nella dichiarazione di classe.
class ContactsTableViewController: UITableViewController { ···
Questa sintassi significa: la classe ContactsTableViewController
è una sottoclasse di UITableViewController
.
Quando si fa clic con il tasto destro su “UITableViewController” mentre si tiene premuto il tasto Option, è possibile vedere nella dichiarazione di classe che UITableViewController
è una sottoclasse di UIViewController
e conforme ai protocolli UITableViewDelegate
e UITableViewDataSource
.
Questa è la potenza del controller di visualizzazione tabella! Non ci fornisce solo i singoli componenti per creare una vista tabella, il controller fornisce anche un’implementazione predefinita. Ecco perché sottoclasse UITableViewController
, invece di creare un controller di visualizzazione vuoto con una vista tabella.
A questo punto, puoi eseguire la tua app con Command-R
o il pulsante Play e vedere il controller di visualizzazione tabella vuoto apparire sullo schermo.
Perché, a proposito? Non abbiamo ancora codificato nulla! Questo perché il controller di visualizzazione tabella ha un’implementazione predefinita, che mostra solo celle vuote sullo schermo. Pulito!
A seconda della versione di Xcode, abbiamo utilizzato il delegato scene per impostare il controller di visualizzazione iniziale del progetto app. Per saperne di più qui: Il delegato di scena in Xcode
Un XIB e un PENNINO sono fondamentalmente la stessa cosa: contengono informazioni sul layout. Un XIB ha un formato XML, mentre un PENNINO ha un formato binario. L’XML viene compilato in binario quando costruisci la tua app, ecco perché le funzioni di UIKit parlano sempre di un “pennino”, mentre Xcode lo chiama sempre “xib”.
Codifica dell’origine dati del controller Vista tabella
Ora che il controller vista tabella è stato impostato, diamo vita! In questo capitolo, ci concentreremo sulle diverse funzioni che è necessario implementare per far funzionare il controller di visualizzazione tabella.
Come spiegato in precedenza, queste funzioni appartengono al delegato del controller vista tabella o all’origine dati del controller vista tabella. Entrambi questi protocolli utilizzano la delega per personalizzare la vista tabella.
Le funzioni più importanti per UITableViewDataSource
sono:
numberOfSections(in:)
tableView(_:numberOfRowsInSection:)
tableView(_:cellForRowAt:)
Altre funzioni rilevanti per UITableViewDelegate
sono:
tableView(_:didSelectRowAt:)
tableView(_:willDisplay:for:)
È possibile trovare ulteriori funzioni nella Documentazione per gli Sviluppatori Apple per UITableViewDelegate e UITableViewDataSource.
Aggiunta dei dati dei contatti
Inizierai aggiungendo i dati delle informazioni di contatto per il controller di visualizzazione tabella. Aggiungere la seguente proprietà alla classe ContactsTableViewController
:
let contacts:] = , , , , , , , , , , , , , , , , ]
E ‘ un rolodex che vorremmo tutti, giusto? Ecco come funziona:
- Il
let contacts
dichiara una costante con nomecontacts
. L’hai aggiunto come proprietà alla classe, quindi ogni istanza di classe ha accesso a questa costante in tutto il codice della classe. - Il tipo di
contacts
è]
, che è array di array di stringhe. Stai essenzialmente creando un array, di cui gli elementi sono array di stringhe. (Un nome di variabile e il suo tipo sono separati da due punti:
) - Il codice
=
assegna un array letterale acontacts
, compilato con i nomi e i numeri di telefono di alcuni miliardari.
In un secondo momento, possiamo usare il numero di elementi nell’array con contacts.count
. E possiamo ottenere singoli nomi e numeri di telefono con contacts
e contacts
, usando la sintassi pedice.
Registrazione di una classe di celle di visualizzazione tabella
Prima di poter utilizzare le celle in un controller di visualizzazione tabella, è necessario registrarle con la vista tabella. Puoi farlo in due modi:
- Fornendo una classe di cella di visualizzazione tabella e un identificatore
- Fornendo una cella di visualizzazione tabella XIB e un identificatore
Quando si utilizza una cella di visualizzazione tabella personalizzata, è molto probabile che si desideri registrare un XIB per questo. Quando si utilizzano le celle di visualizzazione tabella predefinite o altre celle programmatiche, si registra la classe. Useremo la classe, per ora!
Aggiungere il seguente codice alla funzione viewDidLoad()
:
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cellIdentifier")
Assicurati di aggiungerlo sotto la riga super.viewDidLoad()
. Come probabilmente saprai, la funzione viewDidLoad()
fa parte del ciclo di vita del controller di visualizzazione e appartiene alla classe UIViewController
.
Si sta sovrascrivendo la funzione viewDidLoad()
per rispondere a questo evento nel ciclo di vita di un controller di visualizzazione, in modo da poter impostare la vista dopo che è stato caricato. Nel nostro caso, stiamo usando la funzione per registrare la cella di visualizzazione tabella.
Quando si registra una cella di visualizzazione tabella, è necessario fornire anche un identificatore. Questo è semplicemente per associare la classe della cella con un nome che puoi usare in seguito, quando dequeuing la cella in tableView(_:cellForRowAt:)
.
Sei ancora con me? Andiamo avanti!
Implementazione di “numberOfSections(in:)”
La prima funzione delegata che implementeremo è numberOfSections(in:)
.
Una vista tabella può avere più sezioni o gruppi. Ogni gruppo ha un’intestazione che galleggia sopra la riga verticale di celle. In un’app Contatti, è possibile raggruppare i contatti in ordine alfabetico. Questo viene effettivamente fatto nell’app Contatti su iPhone, dove i contatti sono raggruppati A-Z.
L’app che stiamo costruendo ha solo una sezione. Aggiungere la seguente funzione alla classe:
override func numberOfSections(in tableView: UITableView) -> Int{ return 1}
Semplice, vero? La funzione restituisce 1
quando viene chiamata.
Implementazione di “tableView(_:numberOfRowsInSection:)”
Una funzione simile è tableView(_:numberOfRowsInSection:)
. Invece di fornire il numero di sezioni, fornisce il numero di righe in una sezione. Poiché una vista tabella mostra celle in un elenco verticale, ogni cella corrisponde a una riga nella vista tabella.
L’app che stiamo costruendo ha solo una sezione e quella sezione ha un numero di elementi pari al numero di elementi nell’array contacts
. Quindi, questo è contacts.count
!
Aggiungi la seguente funzione alla classe:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{ return contacts.count}
Vedi come funziona? Restituiamo semplicemente contacts.count
. Se si dovesse aggiungere un altro nome e numero di telefono a contacts
, si presenterebbe bene anche nella vista tabella.
Comprendere righe e sezioni
La nostra app Contatti è unidimensionale, mostra solo un elenco di nomi e numeri di telefono e non utilizza gruppi. Ma cosa succede se si dispone di una vista tabella raggruppata?
Nella maggior parte dei casi, anche l’origine dati, come l’array contacts
, sarebbe multidimensionale. Organizzeresti gruppi al primo livello e singoli elementi al secondo livello, “sotto” i gruppi.
- Countries - A - Afghanistan - Albania - ... - B - Bahamas - Bahrain - ... - C - Cambodia - Cameroon - ...
Il numero di gruppi è uguale a countries.count
e il numero di paesi in un singolo gruppo è uguale a countries.count
, dove x
è l’indice della sezione. Tale indice di sezione viene fornito come parametro in tableView(_:numberOfRowsInSection:)
.
Hai notato come queste due funzioni hanno un parametro chiamato tableView
? Questo fa parte del principio di programmazione orientata agli oggetti. Tecnicamente è possibile utilizzare un’origine dati vista tabella e delegare per personalizzare più viste tabella. Dovresti usare tableView
per identificare la visualizzazione della tabella con cui stai lavorando.
Immaginate di avere un app Contatti che può mostrare i numeri di telefono per nome, o numeri di telefono organizzati per azienda. È possibile implementarlo in diversi modi, ad esempio riutilizzando i controller di visualizzazione tabella. O se vuoi riutilizzare il layout della tua app Contatti per visualizzare informazioni simili, come ristoranti, locali o nomi utente Skype? Ecco dove entra in gioco il riutilizzo del codice con OOP!
Fornire celle al controller di visualizzazione tabella
Ci stiamo arrivando! Passiamo alla funzione più importante di un controller di visualizzazione tabella: tableView(_:cellForRowAt:)
.
vedremo di implementare la funzione prima di entrare nei dettagli, ma ci sono un paio di cose che dovete capire su di esso:
- Quando si chiama
- Che un percorso di indice è
- Come si ri-utilizza cellule
in Primo luogo, aggiungere la seguente funzione il ContactsTableViewController
classe:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{}
Ecco come funziona:
- La funzione esegue l’override di implementazione della superclasse da
UITableViewController
. Ormai sai come funziona, vero? Stiamo sovrascrivendo l’implementazione predefinita e sostituiamo la nostra. Questo perchéUITableViewController
ha già implementato il delegato della vista tabella e l’origine dati per noi. - Come prima, la funzione ha un parametro
tableView
che possiamo usare per identificare la vista tabella su cui questa funzione è chiamata. - Un altro parametro è
indexPath
, con etichetta argomentocellForRowAt
. Il percorso dell’indice identifica gli indicirow
esection
della cella. Ne riparleremo piu ‘ tardi. - Il tipo di ritorno della funzione è
UITableViewCell
. Ehi, interessante. Questa funzione viene chiamata dal controller di visualizzazione tabella, ogni volta che è necessario fornire una cella di visualizzazione tabella!
Quando scorri i contatti in questa app, ogni volta che una cella deve essere visualizzata sullo schermo, viene chiamata la funzione tableView(_:cellForRowAt:)
. Ogni volta! Te lo dimostrero ‘ tra un attimo.
Avanti, scriviamo il corpo della funzione. Aggiungere il seguente codice all’interno della funzione:
let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier", for: indexPath)print("\(#function) --- section = \(indexPath.section), row = \(indexPath.row)")cell.textLabel?.text = contactsreturn cell
Ecco cosa succede:
- Innanzitutto, eliminiamo una cella con un identificatore. È esattamente lo stesso identificatore che abbiamo usato prima, quando registravamo la cella. In questo modo la vista tabella sa che tipo di cella vogliamo. La cella dequeued viene assegnata alla costante
cell
. Ora abbiamo una cella di visualizzazione tabella con cui lavorare. Più su dequeuing più tardi. - Quindi, stampiamo alcune informazioni sulla Console. Questo è così che possiamo vedere quando viene chiamata questa funzione, quando viene eseguita l’app.
- Quindi, assegniamo il nome del contatto all’etichetta di testo di questa cella della vista tabella. Il
contacts
contiene il valore del nome del contatto, che otteniamo usandoindexPath.row
. Ogni istanza diUITableViewCell
ha una proprietàtextLabel
diUILabel
e ogni etichetta di quel tipo ha una proprietàtext
. Lo si utilizza per impostare il testo sull’etichetta.
Non preoccuparti, esamineremo ciascuna di queste cose in modo più dettagliato. Per prima cosa, vedi se puoi eseguire la tua app. Vedi i nomi dei contatti? Vedi l’output di debug nella Console? Prova a scorrere l’applicazione!
Quando viene chiamato “tableView(_:cellForRowAt:)”?
Se hai eseguito l’app Contatti e hai giocato con lo scorrimento su e giù, non puoi fare a meno di notare che ogni volta che scorri, l’output di debug viene visualizzato nella Console.
Ogni volta che viene visualizzata una cella che non era sullo schermo prima, viene chiamata la funzione tableView(_:cellForRowAt:)
e viene visualizzata una nuova riga nella Console.
Quindi quando viene chiamato tableView(_:cellForRowAt:)
? Ogni volta che una cella vista tabella deve essere mostrato sullo schermo!
Il controller della vista tabella ha determinato che è necessaria una cella, quindi chiama tableView(_:cellForRowAt:)
. La nostra implementazione di tale funzione elimina una cella, la modifica e la restituisce al controller della vista tabella. Il controller della vista tabella e il framework UIKit lo rendono graficamente sullo schermo.
Che cos’è un percorso indice?
Ogni volta che il controller della vista tabella ha bisogno di una cella da tableView(_:cellForRowAt:)
, fornisce un percorso indice come argomento per la funzione. All’interno del corpo della funzione è possibile utilizzare il parametro indexPath
per sapere esattamente di quale cella ha bisogno il controller della vista tabella.
Un percorso indice è come un indirizzo o una coordinata in una griglia. Un grafico tipico ha un asse X e un asse Y, quindi puoi esprimere una coordinata in quel grafico come x, y
come 0, 1
e 42, 3
. Allo stesso modo, un foglio di calcolo ha righe e colonne con indici.
Una vista tabella utilizza sezioni e righe. Come discusso in precedenza, è possibile utilizzare le sezioni per raggruppare le celle insieme. La nostra app ha solo una sezione e ha contacts.count
righe. Le righe della vista tabella vanno dall’alto verso il basso.
Detto diversamente: le sezioni e le righe di una vista tabella sono ciò che le colonne e le righe sono in un foglio di calcolo. Un percorso indice definisce una posizione nella vista tabella, utilizzando una riga e una sezione.
Le righe e le sezioni sono rappresentate da numeri, chiamati indici. Questi indici iniziano da zero, quindi la prima riga e la sezione avranno il numero di indice 0
.
Quando guardi indietro allo screenshot precedente, ha molto più senso. La prima cella ha percorso indice 0, 0
, la seconda cella 0, 1
, continuando fino all’ultima cella visibile con percorso indice 0, 11
.
Il meccanismo di riutilizzo della vista tabella
Ciò che è più degno di nota della vista tabella è il suo meccanismo per il riutilizzo delle celle. È abbastanza semplice, in realtà.
- Ogni volta che un controller di visualizzazione tabella deve mostrare una cella sullo schermo, viene chiamata la funzione
tableView(_:cellForRowAt:)
, come abbiamo discusso prima. - Invece di creare una nuova cella di visualizzazione tabella ogni volta che viene chiamata quella funzione, preleva una cella creata in precedenza da una coda.
- La cella viene ripristinata in uno stato vuoto, ne cancella l’aspetto e la cella viene nuovamente personalizzata in
tableView(_:cellForRowAt:)
. - Ogni volta che una cella viene fatta scorrere fuori dallo schermo, non viene distrutta. Viene aggiunto alla coda, in attesa di essere riutilizzato.
È abbastanza intelligente, giusto? Invece di creare ed eliminare le celle, è sufficiente riutilizzarle. Ma why perché?
Riutilizzare le celle richiede molto meno memoria. Il controller della vista tabella scriverebbe costantemente in memoria durante la creazione e l’eliminazione delle celle. Anche la gestione della memoria sarebbe più intensa. Quando le celle vengono riutilizzate, la memoria viene utilizzata in modo più efficiente e sono necessarie meno operazioni di memoria.
Inoltre, itt è leggermente meno intensivo della CPU per riutilizzare le celle invece di crearle ed eliminarle, perché semplicemente ci sono meno operazioni coinvolte nel riutilizzo, rispetto alla creazione e all’eliminazione delle celle.
Quando stai scorrendo rapidamente una vista tabella, non stai vedendo nuove celle – stai vedendo le stesse celle più e più volte, con nuove informazioni.
Il codice coinvolto nel riutilizzo delle celle è questo:
let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier", for: indexPath)
La funzione dequeueReusableCell(withIdentifier:)
tenta di dequeue una cella. Quando non ci sono celle nella coda, creerà una cella per noi. L’identificatore viene utilizzato per mantenere ogni tipo di cella sulla propria coda e per assicurarsi che la classe corretta venga utilizzata per creare nuove celle.
Scopri come creare app iOS
Inizia con iOS 14 e Swift 5
Iscriviti al mio corso di sviluppo iOS e scopri come creare fantastiche app iOS 14 con Swift 5 e Xcode 12.
Rispondere all’interazione dell’utente
Manca una cosa dal nostro controller di visualizzazione tabella: la possibilità di chiamare le persone nella nostra lista contatti! Ma prima di farlo, facciamo in modo che si può anche vedere il numero di telefono di un contatto nel controller vista tabella.
La classe UITableViewCell
predefinita ha 4 tipi diversi, come espresso nell’enumerazione UITableViewCellStyle
. È possibile scegliere tra:
-
.default
– una visualizzazione semplice con una riga di testo in nero -
.value1
– una visualizzazione semplice con una riga di testo in nero sulla sinistra, e una piccola etichetta blu sulla destra (utilizzati in app Impostazioni) -
.value2
– una visualizzazione semplice con una riga di testo in nero sulla destra, e una piccola etichetta blu sulla sinistra (utilizzato l’app Contatti) -
.subtitle
– una visualizzazione semplice con una riga di testo in nero, e una piccola riga di testo in grigio sotto di esso
la Maggior parte dei sviluppatori di utilizzare la tabella personalizzata visualizzare le cellule in questi giorni, quindi non vedrete questi tipi di cellule che spesso. Ma sono lì!
Dobbiamo regolare leggermente il codice in tableView(_:cellForRowAt:)
. Sostituire la prima riga della funzione con il seguente codice:
var cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier")if cell == nil{ cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cellIdentifier")}
Se guardi da vicino, vedrai che abbiamo rimosso la parte for: indexPath
della chiamata dequeueReusableCell(...)
. Invece, quella funzione ora restituisce un optional. Quando non può dequeue una cella, la funzione restituisce nil
.
Saltiamo quindi in noi stessi per creare la cella, se è nil
. Lo vedi nella seconda parte del codice. Si utilizza un’istruzione if
condizionale per verificare se cell
è uguale a nil
e, se è vero, si crea la cella utilizzando l’inizializzatore UITableViewCell(style:reuseIdentifier:)
.
Quell’inizializzatore ottiene due argomenti, lo stile della cella .subtitle
e l’identificatore che abbiamo usato in precedenza.
A questo punto abbiamo un problema, perché cell
è un optional ora! Il suo tipo è UITableViewCell?
, ma il tipo di ritorno della funzione richiede che restituiamo un’istanza con tipo non opzionale UITableViewCell
.
Fortunatamente, questo è uno di quei casi in cui possiamo tranquillamente usare la forza per scartare il valore opzionale. A causa del modo in cui il nostro codice è scritto, è impossibile che cell
sia nil
oltre il condizionale. È possibile garantire che cell
non è nil
dopo l’istruzione if
.
Assicurarsi di aggiornare la funzione per utilizzare la forza di scartamento per cell
. Inoltre, aggiungere la seguente riga di codice sotto cell!.textLabel ...
per impostare il sottotitolo della cella mostra il numero di telefono del contatto.
cell!.detailTextLabel?.text = contacts
L’intera funzione ora si presenta così:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{ var cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier") if cell == nil { cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cellIdentifier") } print("\(#function) --- section = \(indexPath.section), row = \(indexPath.row)") cell!.textLabel?.text = contacts cell!.detailTextLabel?.text = contacts return cell!}
Infine, assicurati di rimuovere la seguente riga da viewDidLoad()
. Impedirà alla vista tabella di inizializzare le celle con il tipo sbagliato.
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cellIdentifier")
Mighty fine! Esegui la tua app con Command + R o il pulsante Play e controlla se funziona. Vedi nomi e numeri di telefono? Bene!
Quindi, per la pièce-de-résistance, aggiungiamo quella funzione di interazione utente. Ora che hai imparato le complessità del controller di visualizzazione tabella, penso che tu sappia già come funziona questa prossima funzione.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){ if let url = URL(string: "tel://" + contacts) { UIApplication.shared.open(url) }}
Ancora una volta, stiamo sovrascrivendo l’implementazione predefinita della funzione tableView(_:didSelectRowAt:)
. Questa funzione viene chiamata quando un utente tocca la cella di una vista tabella e appartiene al protocollo UITableViewDelegate
. Come le altre funzioni, ha fornito il percorso dell’indice della cella che è stata toccata.
Nel corpo della funzione, stiamo semplicemente creando un URL tel://
dal numero di telefono. Quindi diciamo all’app di aprire quell’URL, che in modo efficace dice a iOS di avviare una chiamata a questo numero. Quel codice è lì solo a scopo illustrativo. Si noti che questo non funziona su iPhone Simulator, e che i numeri nella nostra applicazione sono falsi. (Ancora, si usa questo codice se si sta facendo un vero e proprio Contatti app!)
È possibile aggiungere il seguente codice alla funzione se si desidera verificare se funziona CORRETTAMENTE.
print("\(#function) --- Calling: \(contacts)")
Questo stamperà un messaggio di debug quando si tocca la cella della vista tabella.
Ulteriori letture
E questo è tutto quello che c’è da fare! È stato un bel viaggio, ma ora sai come funziona un controller di visualizzazione tabella.