2009-09-03 14 views
8

Ho una vista tabella con immagini grandi che riempiono le celle e le altezze delle righe sono impostate in base alla dimensione dell'immagine. Sfortunatamente, la tabella si muove male quando si scorre alla cella successiva.Come posso memorizzare qualcosa per una vista tabella?

Mi è stato detto che il mio tableview scorrerà più facilmente se memorizzo nella cache l'altezza delle righe e le immagini prima che vengano caricate nella tabella. Tutti i miei dati sono memorizzati in un plist.

Come faccio a memorizzare qualcosa nella cache? Che aspetto ha il codice e dove va?

Grazie!

Ecco il mio codice per il caricamento delle immagini:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    static NSString *detailTableViewCellIdentifier = @"Cell"; 

    DetailTableViewCell *cell = (DetailTableViewCell *) 
     [tableView dequeueReusableCellWithIdentifier:detailTableViewCellIdentifier]; 

    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"DetailTableViewCell" owner:self options:nil]; 
    for(id currentObject in nib) 
    { 
     cell = (DetailTableViewCell *)currentObject; 
    } 
    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; 
    NSString *Path = [[NSBundle mainBundle] bundlePath]; 
    NSString *MainImagePath = [Path stringByAppendingPathComponent:([[appDelegate.sectionsDelegateDict objectAtIndex:indexPath.section] objectForKey:@"MainImage"])]; 

    cell.mainImage.image = [UIImage imageWithContentsOfFile:MainImagePath]; 

    return cell; 
} 

Sto anche utilizzando la seguente per calcolare l'altezza della riga:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 
    AppDelegate *appDelegate = (DrillDownAppAppDelegate *)[[UIApplication sharedApplication] delegate]; 
    NSString *Path = [[NSBundle mainBundle] bundlePath]; 
    NSString *MainImagePath = [Path stringByAppendingPathComponent:([[appDelegate.sectionsDelegateDict objectAtIndex:indexPath.section] objectForKey:@"MainImage"])]; 
    UIImage *imageForHeight = [UIImage imageWithContentsOfFile:MainImagePath]; 
    imageHeight = CGImageGetHeight(imageForHeight.CGImage); 
    return imageHeight; 
} 

EDIT: Ecco il codice finale di seguito.

#define PHOTO_TAG 1 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
static NSString *CellIdentifier = @"Photo"; 

UIImageView *photo; 
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 

AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; 
UIImage *theImage = [UIImage imageNamed:[[appDelegate.sectionsDelegateDict objectAtIndex:indexPath.section] objectForKey:@"MainImage"]]; 

imageHeight = CGImageGetHeight(theImage.CGImage); 
imageWidth = CGImageGetWidth(theImage.CGImage); 

if (cell == nil) { 
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 
    photo = [[[UIImageView alloc] initWithFrame:CGRectMake(0, 0, imageWidth, imageHeight)] autorelease]; 
    photo.tag = PHOTO_TAG; 
    [cell addSubview:photo]; 
    } else { 
    photo = (UIImageView *) [cell viewWithTag:PHOTO_TAG]; 
    [photo setFrame:CGRectMake(0, 0, imageWidth, imageHeight)]; 
    } 

photo.image = theImage; 
return cell; 
} 

risposta

16

Il caching non è una panacea per le prestazioni di TableView. Il caching è utile solo se c'è qualcosa di costoso da calcolare e puoi evitare di calcolarlo. Se, d'altra parte, hai semplicemente troppe visualizzazioni nel tuo UITableViewCell, allora il caching non farà nulla per te. Se le tue altezze di riga sono tutte uguali, allora non c'è niente da memorizzare nella cache. Se si utilizza +[UIImage imageNamed:], il sistema sta già memorizzando le immagini nella cache.

Il problema più comune del primo ordine con UITableViewCells sta inserendo troppe visualizzazioni secondarie. Come hai costruito la tua cella? Hai passato del tempo a studiare la Guida alla programmazione di Table View, in particolare A Closer Look at Table-View Cells? Capire questo documento ti farà risparmiare molto tempo dopo.

EDIT: (Basato su codice di cui sopra)

In primo luogo, si sta recupero di una cella riutilizzabile, e poi subito a buttarlo via, la lettura di un pennino e iterare su tutti gli oggetti di primo livello in cerca di una cella (una sembra quasi esattamente come quello che hai appena buttato via). Quindi si elabora una stringa, che si utilizza per aprire un file e leggere il contenuto. Lo fai ogni volta che UITableView vuole una nuova cella, che è molto. E lo fai ancora e ancora per le stesse file.

Quindi, quando UITableView vuole conoscere l'altezza, si legge di nuovo l'immagine dal disco. E lo fai ogni volta che UITableView ti chiede (e potrebbe chiedere molte volte la stessa riga, sebbene cerchi di ottimizzarlo).

Si consiglia di iniziare leggendo il collegamento della guida alla programmazione UITableView I sopra. Speriamo che questo possa aiutare molto. Quando hai fatto questo, qui ci sono le cose che si dovrebbe pensare:

  • È indicato che non v'è altro che una singola visualizzazione dell'immagine in questa cella. Hai davvero bisogno di un NIB per questo? Se si applica una NIB (e in alcuni casi è necessario utilizzarli), leggere la Guida alla programmazione su come implementare una cella con base NIB. Dovresti utilizzare IBOutlet, non tentare di eseguire iterazioni sugli oggetti di livello superiore.

  • +[UIImage imageNamed:] trova automaticamente i file nella directory delle risorse senza dover calcolare il percorso del pacchetto.Sarà anche cache quelle immagini per voi automaticamente.

  • Il punto di -dequeueReusableCellWithIdentifier: consiste nel recuperare una cella che UITableView non utilizza più e che è possibile riconfigurare anziché crearne una nuova. Lo chiami, ma lo butti via immediatamente. Dovresti controllare se è tornato a zero, e solo caricarlo fuori dalla NIB se lo ha fatto. Altrimenti, devi solo cambiare l'immagine. Di nuovo, leggi la Guida alla programmazione; ne ha molti, molti esempi. Assicurati solo di provare veramente a capire cosa sta facendo -dequeueReusableCellWithIdentifier: e non trattarlo come qualcosa che scrivi a questo punto del programma.

+0

Rob, Grazie per la risposta. Ho solo una vista per la cella e questa è una singola immagine. Ho avuto l'idea di mettere in cache le immagini di una domanda precedente che ho chiesto: http://stackoverflow.com/questions/1352479/tricks-for-improving-iphone-uitableview-scrolling-performance – Jonah

+0

Ho aggiunto il codice sopra nel caso in cui sia presente Aiuto. Grazie! – Jonah

+0

Le risposte di rpetrich sono buone. Per quanto riguarda il caching rowHeight, la soluzione più semplice consiste nel mantenere un array di NSNumbers che memorizzino l'altezza calcolata per ogni riga. Puoi iniziare facendo in modo che siano tutti 0 e, se è 0, lo calcoli e memorizzi il risultato nell'array. Se non è zero, lo restituisci. Fai un po 'di profilazione, però, in Strumenti e dai un'occhiata a dove stai * davvero * spendendo il tuo tempo prima di fare troppe modifiche casuali. I calcoli dell'altezza della riga possono essere l'ultimo dei tuoi problemi. Forse stai ridimensionando troppo le immagini (sembra probabile). Strumenti aiuteranno. –

4

Se si ha bisogno di memorizzare nella cache le altezze, ho fatto qualcosa di simile (altezze di caching per una cella di visualizzazione di un oggetto "articolo" - articolo forse una delle diverse sottoclassi):

+ (CGFloat) heightForArticle: (Article*) article atWidth: (CGFloat) width { 

    static NSCache* heightCache = nil; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     heightCache = [NSCache new]; 
    }); 

    NSAssert(heightCache, @"Height cache must exist"); 

    NSString* key = @"unique"; //Create a unique key here 
    NSNumber* cachedValue = [heightCache objectForKey: key]; 
    if(cachedValue) 
     return [cachedValue floatValue]; 
    else { 
     CGFloat height = 40;//Perform presumably large height calculation here 

     [heightCache setObject: [NSNumber numberWithFloat: height] forKey: key]; 

     return height; 
    } 
} 
+0

Questo mi ha davvero aiutato, l'ho usato per memorizzare l'altezza della cache e anche per memorizzare nella cache le immagini delle celle di visualizzazione tabella. Grazie :) – Supertecnoboff

+0

In realtà con rispetto, ma riprendo il mio commento. Questo non funziona, ho notato che a volte, restituisce i valori di altezza sbagliati. Quindi le celle finiscono per essere troppo grandi o troppo piccole, a volte. – Supertecnoboff

Problemi correlati