2012-05-15 14 views
6

I have UITableView. nel metodo tableView:cellForRow:atIndexPath: (quando i dati vengono inseriti nelle celle) ho implementato una sorta di caricamento lento. Se non ci sono oggetti per chiave (tasto == numero riga) nel rowDataNSDictionary il programma avvia in background il metodo requestDataForRow:. quindi i dati nelle celle vengono popolati un po 'dopo che la cella diventa visibile. Ecco il codice:UITableView ottimizzazione caricamento lazy

static int requestCounter=0; 

-(void)requestDataForRow:(NSNumber *)rowIndex 
{ 
    requestCounter++; 
    //NSLog(@"requestDataForRow: %i", [rowIndex intValue]); 
    PipeListHeavyCellData *cellData=[Database pipeListHeavyCellDataWithJobID:self.jobID andDatabaseIndex:rowIndex]; 
    [rowData setObject:cellData forKey:[NSString stringWithFormat:@"%i", [rowIndex intValue]]]; 
    requestCounter--; 

    NSLog(@"cellData.number: %@", cellData.number); 

    if (requestCounter==0) 
    { 
     //NSLog(@"reloading pipe table view..."); 
     [self.pipeTableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO]; 
    }; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *MyIdentifier = @"pipeCellIdentifier"; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier]; 
    [[NSBundle mainBundle] loadNibNamed:@"PipesForJobCell" owner:self options:nil]; 
    cell = pipeCell; 
    self.pipeCell = nil; 


    PipeListHeavyCellData *cellData=[[PipeListHeavyCellData alloc] init]; 

    if ([rowData objectForKey:[NSString stringWithFormat:@"%i", indexPath.row]]==nil) 
    { 
     //NSLog(@"  nil data for row: %i", indexPath.row); 
     [self performSelectorInBackground:@selector(requestDataForRow:) withObject:[NSNumber numberWithInt:indexPath.row]]; 
    } 
    else 
    { 
     //NSLog(@"  has data for row: %i", indexPath.row); 
     PipeListHeavyCellData *heavyData=[[PipeListHeavyCellData alloc] init]; 
     heavyData=(PipeListHeavyCellData *)[rowData objectForKey:[NSString stringWithFormat:@"%i", indexPath.row]]; 
     cellData._id=[heavyData._id copy]; 
     cellData.number=[heavyData.number copy]; 
     cellData.status=[heavyData.status copy]; 
}; 

Questo codice funziona, tutto è OK, MA mio tavolo ha 2000 righe e se gli utenti scorre da cellule con indice 10 per cella con l'indice 2000 molto rapidamente. Deve attendere a lungo fino a quando tutte le richieste di estrazione dei dati non verranno completate (per le righe 11, 12, 13, ..., 2000), perché le righe diventano visibili mentre l'utente stava scorrendo la vista tabella, quindi è stato chiamato il metodo requestDataForRow.

Come posso ottimizzare queste cose?

+1

Ecco una grande domanda con lo stesso problema con diverse soluzioni molto buone (con codice): http://stackoverflow.com/q/7567827/937822 – lnafziger

risposta

4

Ho dovuto fare qualcosa di simile. Dovrai creare una coda che elabori prima gli elementi aggiunti più di recente.

Ad esempio, l'utente apre la tabella e 10 richieste vengono messe in coda. Si rimuove il primo oggetto e si avvia il recupero dei dati per la prima riga. Tuttavia, l'utente scorre quindi verso il basso fino alle righe da 31 a 40. Dovrai quindi inserire tali righe prima dei primi 10 nella tua coda perché ora hanno una priorità più alta. La chiave è che non si avviano immediatamente 10 richieste contemporaneamente, ma le si elabora in ordine. In questo modo, quando l'utente scorre, si "spreca" una sola richiesta - l'ultima richiesta che è stata fatta.

Un modo semplice per implementare questo è utilizzare [tableView indexPathsForVisibleRows].

+0

Grazie, i miei pensieri sono simili. – user1385666