2013-06-18 11 views
7

Non riesco a capire come funziona. Ho letto molti thread su SO su di esso - come ad esempio UITableView dequeueReusableCellWithIdentifier Theory e How does dequeueReusableCellWithIdentifier: work?.Informazioni su UITableView dequeueReusableCellWithIdentifier - restituisce la cella anche alla prima chiamata

Tuttavia, il mio UITableView riattacca ogni volta una cella ogni volta (non è mai nulla), anche quando viene caricata per la prima volta. Avevo l'impressione che celle simili dovessero usare lo stesso identificatore, quindi devi solo cambiare ciò che è necessario.

Perché

if (!cell) { 
    NSLog(@"New cell"); 
    cell = [[UITableViewCell alloc] initWithStyle:someStyle reuseIdentifier:someIdentifier]; 
} 

non viene mai chiamato, io non sono sicuro di come dovrei gestire celle della stessa tabella con stili diversi, perché lo stile può essere impostato solo nel inizializzatore.

Ho anche provato a utilizzare identificativi di cella diversi, per assicurarmi che non riutilizzasse le celle da una tabella diversa o qualcosa del genere. Sto registrando questi identificatori con [tableView registerClass: forCellReuseIdentifier:]

Se ho capito, questo metodo dovrebbe restituire solo le celle create in precedenza che sono state spostate dallo schermo (nascosto, cioè può essere riutilizzato). Allora come mai restituisce una cella la prima volta che viene chiamata?


Edit: Così la confusione stava usando [tableView dequeueReusableCellWithIdentifier: forIndexPath:] invece di [tableView dequeueReusableCellWithIdentifier:] (il primo richiede la registrazione l'identificatore, il secondo tornerà a zero se nessuno è disponibile - il comportamento mi aspettavo sopra).

Tuttavia, ho notato che quando ho cambiato il mio codice per utilizzare [tableView dequeueReusableCellWithIdentifier:], crea una nuova cella e la sua contentView.frame ha una larghezza di 320 (larghezza intera). Prima, quando facevo il dequeue...forIndexPath darebbe una larghezza di 302, o la larghezza visuale/"reale" della cella. Perchè è questo?

Inoltre, c'è un modo per specificare lo stile di UITableViewCells regstiered per il riutilizzo?


Soluzione: Così ho trovato questa discussione UITableView cell.contentView.bounds.size.width Changes With Cell Reuse, che dice quando si imposta l'autoresizingmask per UIViewAutoresizingFlexibleLeftMargin, che è fisso quando si tenta di fare il posizionamento relativo (la larghezza contentView è inizialmente la piena larghezza, ma quando presentarlo è ridotto, quindi se fai i tuoi calcoli, verrà comunque visualizzato correttamente).

Stavo posizionando un UISwitch sulla destra - e quando ho impostato la maschera di autoresizzazione funziona quando è visualizzata per la prima volta, ma spostato su altri ~ 20 pixel quando l'ho acceso. Non so cosa abbia causato quel cambiamento in più, ma ho finito per risolverlo semplicemente impostando l'UISwitch come accessorio della cellaView.

(Questo è parzialmente fuori tema dalla domanda originale, ma se qualcuno dovesse inciampare su questo forse sarebbe utile). Per chiunque si interroghi in modo specifico sulla domanda originale, la risposta è sotto la prima modifica.

+1

Le celle sono state create in un UITableViewController da uno storyboard? – danypata

+0

Tutti creati a livello di codice ... sì, molte persone dicono di usare lo storyboard ...ma non mi sono abituato e sento che lo capirò meglio sapendo cosa capisco in realtà – Raekye

+1

Nessun problema, ma mi chiedevo perché quando stai creando le celle in un UITableViewContoller da uno storyboard 'il metodo restituirà sempre una cella valida (se viene utilizzato l'identificatore corretto) – danypata

risposta

8

Quando si chiama [tableView registerClass: forCellReuseIdentifier:], si sta insegnando alla visualizzazione tabella cosa fare quando si utilizza in seguito lo ReuseIdentifier specificato. Così, quando si chiama in seguito [tableView dequeueReusableCellWithIdentifier:] sarà o:

A. Ottenere una cellula che si è creato in precedenza e non è attualmente utilizzato

O

B. Creare una nuova cella della classe hai specificato

Quindi, quando si deseleziona, si ottiene sempre un'istanza. Se vuoi creare nuove istanze di celle tu stesso con initWithStyle:reuseIdentifier:, non dovresti registrare una classe con la vista tabella. In alternativa, lasciare la registrazione e aggiungere la logica per specificare tutto ciò che deve essere configurato (e considerare l'utilizzo di più classi di celle diverse e riutilizzare gli identificatori).

+1

Se tolgo il' [tableView registerClass: forCellReuseIdentifier:] ', ottengo un "NSInteralInconsistencyException: impossibile disconnettere una cella con identificatore [identificativo mio]". E quando eseguo la registrazione, restituisce sempre una cella, anche se sto usando identificatori diversi, quindi non posso creare diversi stili di cella – Raekye

+0

Devi usare 'dequeueReusableCellWithIdentifier: forIndexPath:' allora - richiede che tu registri un classe o NIB. Potresti voler mostrare il codice per le tue registrazioni e 'tableView: cellForRowAtIndexPath:' se vuoi più aiuto. – Wain

+0

Sì, l'ho appena notato in un'altra domanda. Quindi utilizzare il metodo senza un percorso dell'indice funziona come previsto, ma ora c'è un altro problema (aggiornamento del questino) – Raekye

0

perché la prima volta la cella è pari a zero che è il motivo per cui questo viene chiamato:

if (!cell) { 
NSLog(@"New cell"); 
cell = [[UITableViewCell alloc] initWithStyle:someStyle reuseIdentifier:someIdentifier]; 
} 

ma poi se la cella è già pronto per il riutilizzo e fondamentalmente la sua non nullo - restituisce la cella e non lo fa premere il suddetto se dichiarazione

+0

L'intero punto della domanda è che la prima volta non è nil – Raekye

0

Dalla documentazione di mele a https://developer.apple.com/library/ios/#documentation/UIKit/Reference/UITableView_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40006943

chiamare questo metodo dal vostro oggetto origine dei dati quando gli viene chiesto di fornire una nuova cella per la visualizzazione della tabella. Questo metodo rimuove una cella esistente se ne è disponibile una o ne crea una nuova utilizzando il file di classe o pennino precedentemente registrato. Se nessuna cella è disponibile per il riutilizzo e non hai registrato un file di classe o pennino, questo metodo restituisce zero.

Il metodo dequeue sarà

  1. ritorno una cella riciclato, se disponibile

  2. Crea una nuova cella se ti sei registrato una (lei ha citato avete fatto queste cose)

  3. Se nessuno di questi è vero, restituisce nil

Suppongo che se si rimuove la registrazione (che potrebbe essere nascosta in uno xib), si otterrà il risultato nullo.

+0

Non sto usando il generatore di intercae. Il punto centrale della mia domanda era che non restituisce mai nulla. In termini di "restituire una cella riciclata", è possibile avere una cella riciclata quando si avvia per la prima volta l'applicatino? – Raekye

+0

La prima cella non viene riciclata, è appena stata creata automaticamente dalla vista tabella. – Wain

+0

Sì, grazie, ho trascurato la differenza tra la versione con 'forIndexPath:' e quella senza – Raekye

-1

se si vede UITableView.h

A partire dal iOS 6, i clienti possono registrare un pennino o di classe per ogni cella.

Se tutti gli identificatori di riutilizzo sono registrati, utilizzare il più recente - dequeueReusableCellWithIdentifier:forIndexPath: per garantire che venga restituita un'istanza di cella.

Anche le istanze restituite dal nuovo metodo di richiesta di addebito vengono ridimensionate correttamente quando vengono restituite.

(void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(5_0); 

(void)registerClass:(Class)cellClass forCellReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(6_0); 
Problemi correlati