2011-09-27 11 views
10

Forse un duplicato ma non ho trovato una domanda specifica su SO, quindi eccolo qui.Best practice per il disegno dinamico UITableView row height

Sono curioso di cambiare le altezze dinamicamente per tutte le righe, in genere, perché non si conosce la lunghezza di una NSString utilizzata per un'etichetta.

so è necessario utilizzare questo metodo delegato per modificare l'altezza delle righe:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 

Il problema è questo metodo delegato viene chiamato prima della creazione della cellula (cioè chiamato prima cellForRowAtIndexPath).

Quindi, quello che ho pensato è creare una cella fittizia in viewWillAppear e un metodo che aggiunge altezze di cella a un array che si associa all'origine dati della vista tabella (che nel mio caso è anche un array).

viewWillAppear implementa questo un metodo importante per ottenere l'altezza:

[NSString sizeWithFont: constrainedToSize: lineBreakMode:]

Poi nel heightForRowAtIndexPath posso restituire l'altezza della cella in questo modo:

//cellHeights is an ivar populated in viewWillAppear 
return [[cellHeights objectAtIndex:indexPath.row] floatValue]; 

mi chiedevo se ci fosse un modo migliore per modificare dinamicamente l'altezza della riga?

Mi rendo conto che questo peggiorerà le prestazioni per un numero elevato di righe (maggiore di 1000, credo). Ma nel mio caso, le mie file non si avvicinano mai a quel numero. Quindi il successo in termini di prestazioni è trascurabile.

Grazie in anticipo!

risposta

8

Ottima domanda! In effetti, ho fatto qualcosa di simile in alcune delle mie applicazioni.

Posso pensare a un paio di alternative, ma tutte sono sullo stesso tema. Puoi anche utilizzare sizeWithFont: all'interno di heightForRowAtIndexPath: e rimuovere l'array. In tal caso, puoi eseguire un riscontro di prestazioni per ricalcolare le dimensioni ogni volta, se l'operazione è costosa.

Si potrebbe fare "lazy loading" del cellHeights serie all'interno diheightForRowAtIndexPAth: quindi potrebbe essere simile a questa:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
    if ([cellHeights objectAtIndex:indexPath.row] == nil) { 
     ... calculate height and store it in the array at the correct index... 
    } 

    return [[cellHeights objectAtIndex:indexPath.row] floatValue]; 
} 

Il vantaggio sto pensando è che si solo calcolare le altezze per le celle che verranno sicuramente caricate. Se esegui il calcolo in viewWillAppear, suppongo che finisci per farlo per ogni cella, indipendentemente dal fatto che sia visualizzato?

Infine, è possibile inserire le dimensioni nel proprio modello di dati. Se è, ad esempio, una matrice di stringhe, è possibile creare una classe che abbia due proprietà: una stringa e una proprietà "representationSize". Quindi è possibile ricalcolare la dimensione della stringa ogni volta che viene modificato il valore della stringa. Quindi, ci sarebbe solo un array, non due, che si mapperebbe sull'origine dati, riempito con una classe di dati contenente sia la stringa che la dimensione di visualizzazione della stringa, e il valore sarebbe calcolato quando la stringa cambia, per niente una volta quando appare la vista.

Ad ogni modo, mi piacerebbe sentire alcuni commenti su questi diversi approcci.

+0

Peccato. Speravo anche in altre risposte. Grazie per il tuo contributo! –

1

Ho troppo problema nel mio UITableView, quando scorro tableview (su iPhone 3gs). Ho visto un sacco di ritardi. Così apro il profiler del tempo (ottimo strumento per l'ottimizzazione) e il problema è stato quando ho chiamato function sizeWithFont. La soluzione migliore per risolvere questo problema è chiamare sizeWithFont nel costruttore.