2010-08-23 8 views
32

Quando Apple ha sviluppato lo 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.UITableView dequeueReusableCellWithIdentifier Theory

"allocazione degli oggetti ha un costo delle prestazioni, soprattutto se l'assegnazione deve avvenire più volte nel corso di un breve periodo per esempio, quando i utente scorre una vista tabella. Se si riutilizzano le celle invece di allocare quelli nuovi, si migliora notevolmente le prestazioni della visualizzazione della tabella. "

Fonte: iOS Reference Library

Per riutilizzare una cella che si utilizza:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 

Ora, quello che mi chiedo è: cosa succede in realtà 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 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é ha troppo). Quando una cella scompare dallo schermo verrà inserita nella coda di riutilizzo di TableView. Quando è necessaria una nuova cella, guarda nella coda se è disponibile una cella con lo stesso identificatore, invoca il metodo prepareForReuse su quella cella e si rimuove dalla coda.

+0

Risposta breve: Sì. Ha una coda/set di riutilizzo separata che non è la stessa cosa già presente nella tabella. –

risposta

43

dequeueReusableCellWithIdentifier: restituisce solo cell se è stato contrassegnato come pronto per il riutilizzo. Questo è il motivo per cui in quasi ogni cellForRowAtIndexPath: metodo si vedrà qualcosa di simile

 


UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 

if (nil == cell) { 
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
            reuseIdentifier:CellIdentifier]; 
} 

// Do something to cell 

return cell; 
 

In effetti, abbastanza righe verranno assegnati per riempire la parte visibile della tableview (più uno o due in più). Come da schermo cells scroll, vengono rimossi dallo table e contrassegnati come pronti per reuse. Man mano che la coda di "celle disponibili" aumenta, la linea che richiede uno dequeued cell inizierà a ottenere un cell da utilizzare, a quel punto non sarà più necessario allocare.

+3

La parte "uno o due più" non è corretta. Ha assegnato * esattamente * ciò che è necessario. Fai una prova e vedrai. –

+0

Proprio come St3fan dice che se NSLog il metodo in cui richiede una cella lo vedrai chiede solo la cella che è necessaria. – Mark

+2

Ero forse un po 'frettoloso nel modo in cui l'ho spiegato. "Ciò che è necessario" varia a seconda delle circostanze. Quando inizi a scorrere UITableView, entrano in gioco più fattori. Un esempio: se si scorre molto velocemente una vista tabella lunga, è possibile far sì che la tabella richieda una cella quando nessuna è disponibile per rimpicciolire. –

13

Il codice per deqeueueReusableCellsWithIdentifier: sarà simile a questo:

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

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

Così mantiene un semplice NSMutableSet con oggetti riutilizzabili.

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

Quindi si inizia con un set vuoto e l'insieme crescerà solo se effettivamente ci sono più dati da mostrare, quindi è visibile sullo schermo.

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

2

Lo scopo di dequeueReusableCellWithIdentifier è di utilizzare 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 quello dequeueReusableCellWithIdentifier inizializzare il numero specifico di celle che abbiamo creato e le celle utilizzeranno ancora 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; 
} 
Problemi correlati