UITableView dequeueReusableCellWithIdentifier Theory

Quando Apple ha sviluppato UITableView per il primo iPhone ha avuto un problema nelle prestazioni durante lo scorrimento. Poi un ingegnoso ingegnere ha scoperto che la causa di ciò era che l’allocazione di oggetti comportava un prezzo, quindi ha escogitato un modo per riutilizzare le celle.

“L’allocazione degli oggetti ha un costo in termini di prestazioni, soprattutto se l’allocazione deve avvenire ripetutamente in un breve periodo, ad esempio quando l’utente scorre una tabella: se riutilizzi le celle invece di allocarne di nuove, aumenti notevolmente le prestazioni della visualizzazione della tabella.”

Fonte: libreria di riferimento iOS

Per riutilizzare una cella usi:

 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 

Ora, quello che mi chiedo è, cosa succede realmente qui? Ti sembra nel TableView se c’è una cella con quell’identificatore e lo restituisce? Beh, sì, ma se invia un riferimento invece di allocare e ho una vista tabella con diciamo 4 celle con lo stesso identificatore tutte visibili. Come può moltiplicarsi in quattro istanze senza allocare?

Voglio sapere questo perché sto costruendo un componente di tipo calendario e tutte le celle hanno la stessa struttura solo il testo all’interno delle modifiche. Quindi se potessi in qualche modo riutilizzare le mie celle invece di allocarle, penso che potrei ottenere una performance migliore.

La mia teoria è che assegna le quattro celle (semplicemente perché lo ha anche). Quando una cella scompare dallo schermo verrà inserita nella coda di riutilizzo di TableView. Quando una nuova cella è necessaria, guarda nella coda se è disponibile una cella con lo stesso identificatore, invoca il metodo prepareForReuse su quella cella e si rimuove dalla coda.

dequeueReusableCellWithIdentifier: restituisce una cell se è stata contrassegnata come pronta per il riutilizzo. Questo è il motivo per cui in quasi ogni cellForRowAtIndexPath: metodo vedrai qualcosa di simile

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (nil == cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } // Do something to cell return cell;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (nil == cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } // Do something to cell return cell; 

In effetti, verranno allocate abbastanza righe per riempire la parte visibile della vista tableview (più una o due). Quando le cells scroll dallo schermo, vengono rimosse dalla table e contrassegnate come pronte per essere reuse . Man mano che la coda delle “celle disponibili” cresce, la linea che richiede una dequeued cell inizierà a ottenere una cell da utilizzare, a quel punto non sarà più necessario allocare.

Il codice per deqeueueReusableCellsWithIdentifier: sarà simile a questo:

(Tratto da uno dei miei progetti in cui faccio qualcosa di simile con viste / pagine in una vista di scorrimento paginata)

 - (UIView*) dequeueReusablePage { UIView* page = [reusablePages_ anyObject]; if (page != nil) { [[page retain] autorelease]; [reusablePages_ removeObject: page]; } return page; } 

Quindi mantiene un semplice NSMutableSet con oggetti riusabili.

Quando le celle scorrono dallo schermo e non sono più visibili, vengono inserite in questo set.

Quindi inizi con un set vuoto e il set crescerà solo se avrai effettivamente più dati da mostrare, quindi sarà visibile sullo schermo.

La cella usata scorre fuori dalla parte superiore dello schermo, viene inserita nel set, quindi viene presa per la cella che appare nella parte inferiore dello schermo.

Lo scopo di dequeueReusableCellWithIdentifier è di usare meno memoria. se utilizziamo 100 celle in una tabellaView, è necessario creare ogni volta 100 celle. Riduce la funzionalità dell’app e può causare arresti anomali. Per quel dequeueReusableCellWithIdentifier inizializza il particolare numero di celle che abbiamo creato e le celle useranno di nuovo per ulteriori elaborazioni.

 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *TableIdentifier = @"YourCellIdentifier"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TableIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TableIdentifier]; } ExternalClassTableViewCell *myCell = [[ExternalClassTableViewCell alloc]init]; myCell.MyCellText.text = [tableData objectAtIndex:indexPath.row]; myCell.MyCellImage.backgroundColor = [UIColor blueColor]; return cell; }