2011-02-11 6 views
7

Ho un UITableView con un elenco di elementi, ognuno con la propria immagine. Pensavo che il progetto di esempio di LazyTableImages di Apple sarebbe stato perfetto da cui apprendere e utilizzare per implementare lo stesso tipo di processo di download delle immagini in modo asincrono, dopo che i dati dell'elenco originale sono stati recuperati.Domanda sull'esempio LazyTableImages di Apple - Non si comporta esattamente come l'app store

Per la maggior parte, funziona abbastanza bene, tranne che ho notato una sottile differenza di comportamento, tra questa app di esempio e il modo in cui l'app store reale scarica le immagini.

Se si avvia il campione LazyTableImages, poi fare un rapido movimento-scorrere verso il basso, vedrete che le immagini non vengono visualizzate fino dopo lo scorrimento arriva ad un arresto completo.

Ora, se esegui lo stesso test con un elenco di elementi nell'app store effettivo, vedrai che le immagini iniziano a essere visualizzate non appena i nuovi elementi vengono visualizzati, anche se lo scorrimento non è ancora terminato .

Sto provando a raggiungere gli stessi risultati, ma finora non sto facendo progressi. Qualcuno ha qualche idea su come farlo?

Grazie!

risposta

10

Sono sconcertato che nessuno potrebbe rispondere a questa ...

Così, alla fine ho capito come acheive il esatto stesso effetto che viene utilizzato nel negozio reale applicazione, per quanto riguarda come le icone vengono scaricati/visualizzati.

Prendere il progetto di esempio LazyTableImages e apportare alcune semplici modifiche.

  1. Vai nel controllore vista radice e rimuovere tutti i controlli relativi a ping scorrimento e/o decelerazione a cellForRowAtIndexPath

  2. Rimuovere tutte le chiamate a loadImagesForOnScreenRows, e quindi rimuovere tale metodo pure.

  3. Andate in IconDownload.m e cambiare il metodo di startDownload non fare un'immagine downlaod asincrona, ma invece fare un download di sincronizzazione su un thread in background.Rimuovere tutto il codice nella startDownload, e aggiungere la seguente, in modo che assomiglia a questo:

 

- (void)startDownload 
{ 
    NSOperationQueue *queue = [NSOperationQueue new]; 
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(loadImage) object:nil]; 

    [queue addOperation:operation]; 

    [operation release]; 
    [queue release]; 
} 
 

Poi, aggiungere un loadImage, come questo:

 

- (void)loadImage 
{ 
    NSData *imageData = [[NSData alloc] initWithContents OfURL:[NSURL URLWithString:appRecord.imageURLString]]; 
    self.apprecord.appIcon = [UIImage imageWithData:imageData]; 
    [imageData release]; 

    [self performSelectorOnMainThread:@selector(notifyMainThread) withObject:nil waitUntilDone:NO]; 
} 
 

Quindi, aggiungere notifyMainThread come questo :

 

- (void)notifyMainThread 
{ 
    [delegate appImageDidLoad:self.indexPathInTableView]; 
} 
 

Fatto! Eseguilo e vedrai il comportamento esatto dell'app store, non più in attesa di richiedere il download delle immagini finché non si interrompe lo scorrimento e non dovrai più aspettare che le immagini vengano visualizzate finché lo scorrimento non si interrompe o finché l'utente non ha rimosso il dito dallo schermo.

Le immagini vengono scaricate non appena la cella è pronta per essere visualizzata e l'immagine viene visualizzata non appena scaricata, punto.

Ci scusiamo per eventuali errori di battitura, non ho incolla questo dalla mia app, ho digitato in, dato che sono lontano dal mio Mac in questo momento ...

In ogni caso, spero che questo aiuta tutti voi. ..

+0

Brillante! Grazie per aver postato questo! –

+0

Apprezzo il tuo sforzo per migliorare l'esempio di Apple. La tua soluzione funziona parzialmente. I delegati di scorrimento dovrebbero ** NON ** essere rimossi, oppure il controller di visualizzazione non sa quando iniziare a scaricare le icone. Il 'loadImagesForOnScreenRows' dovrebbe anche essere chiamato in' viewDidLoad' o 'viewDidAppear', dipende dall'utilizzo. – Raptor

+0

Bello, ma cambia l'intero codice di esempio. Non usa più NSURLConnection. – yosh

0

Check out UIScrollViewDelegate. Ho implementato qualcosa di simile ascoltando scrollViewDidScroll:, calcolando la velocità di scorrimento (controllando lo contentOffset contro l'ultimo registrato contentOffset, diviso per la differenza di tempo) e iniziando a caricare le immagini quando la velocità scende sotto una certa soglia. (È possibile ottenere qualcosa di simile con UIScrollViewDelegate's scrollViewDidEndDragging:willDecelerate:).

Naturalmente, non è necessario controllare la velocità; puoi semplicemente caricare le immagini su di UITableViewDelegate ogni volta che vedi una nuova cella, ma ho scoperto che se l'utente sta sfogliando tonnellate di celle, non devi preoccuparti finché non vedi che stanno andando a rallentare giù per navigare.

+0

Ho provato questo. Ho verificato che le chiamate per scaricare le immagini degli oggetti appena visualizzate stanno accadendo immediatamente. Tuttavia, connectionDidFinishLoading: non viene mai chiamato finché lo scorrimento non si ferma completamente. Sono davvero confuso da questo comportamento ... – bpatrick100

+0

Un altro modo per descrivere il comportamento dell'app di esempio, è che se fai scorrere l'elenco verso l'alto, ma non rilasciare il dito (tienilo sullo schermo), vedrai che il le immagini non vengono visualizzate. Quindi, non appena si rilascia il dito, verranno visualizzate le immagini. Sembra un comportamento a thread singolo. Mi chiedo se questo è l'intero problema qui. Mi chiedo se ho bisogno di mettere esplicitamente ciascuna delle chiamate di download di immagini sul proprio thread ... – bpatrick100

+0

Dovrebbe essere sufficiente allocare un solo thread per tutte le chiamate di download. Per quanto riguarda le connessioni in generale, ti consiglio ASIHTTPRequest (http://allseeing-i.com/ASIHTTPRequest/) – kevboh