2012-12-13 3 views
7

Sono abbastanza nuovo per Objective-C quindi spero che tutto ciò abbia un senso. Ho scaricato le immagini da un server e le ho visualizzate in una vista immagine nel metodo collectionView cellForItemAtIndexPath:. Il problema che sto affrontando è che le immagini non sembrano essere nella cache. Sembra che ogni volta che una cella viene riutilizzata, l'immagine associata dal server venga nuovamente scaricata.Memorizzazione nella cache di un'immagine e UICollectionView

Nel mio metodo viewDidLoad Sto creando un NSMutableDictionary:

imageDictionary = [[NSMutableDictionary alloc]initWithCapacity:50.0]; 

Dalla lettura della documentazione e guardando le risposte alle domande simili ho pensato che questo, più il seguente codice sarebbe sufficiente. Sono stato a questo per un paio di giorni e so che c'è qualcosa che mi manca o un concetto che non sto afferrando.

#pragma mark - UICollectionView Data Source 
- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section;{ 
    NSLog(@"Begin retrieving photos"); 
    return [self.photos count]; 
} 

-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{ 
    return 1; 
} 

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;{ 
    CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"MY_CELL" forIndexPath:indexPath]; 
    cell.imageView.image = nil; 

    if (cell.imageView.image == nil) { 
    dispatch_queue_t downloadQueue = dispatch_queue_create("image downloader", NULL); 
    dispatch_async(downloadQueue, ^{ 
     NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[self.photos objectAtIndex:indexPath.row] objectForKey:@"fullimage"]]]; 
     UIImage *image = [UIImage imageWithData:data]; 
     [imageDictionary setObject:image forKey:@"Image"]; 

     dispatch_async(dispatch_get_main_queue(), ^{ 
      cell.imageView.image = [imageDictionary objectForKey:@"Image"]; 
      [cell setNeedsDisplay]; 
     }); 
    }); 
    } 
    return cell; 
} 

Qualsiasi aiuto sarebbe molto apprezzato. Grazie in anticipo.

+2

Sembra che si stia scaricando di nuovo l'immagine ogni volta. La collectionview non memorizza nella cache le immagini per te. Avrai bisogno di creare il tuo dizionario per la memorizzazione nella cache. Guarda in NSCache. – yuf

+0

@yuf lo farà - grazie! – BrianS

risposta

15

@yuf - grazie ancora per la direzione. NSCache sembra aver ottenuto i risultati che cercavo. Ecco il codice che funziona correttamente. Se qualcuno ha un problema simile, puoi confrontare quanto segue alla mia domanda originale.

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;{ 
    CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"MY_CELL" forIndexPath:indexPath]; 

    NSString *imageName = [[self.photos objectAtIndex:indexPath.row] objectForKey:@"fullimage"]; 
    UIImage *image = [imageCache objectForKey:imageName]; 

    if(image){ 

     cell.imageView.image = image; 
    } 

    else{ 

    cell.imageView.image = nil; 

    dispatch_queue_t downloadQueue = dispatch_queue_create("image downloader", NULL); 
    dispatch_async(downloadQueue, ^{ 

     NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[self.photos objectAtIndex:indexPath.row] objectForKey:@"fullimage"]]]; 
     UIImage *image = [UIImage imageWithData:data]; 

     dispatch_async(dispatch_get_main_queue(), ^{ 

      cell.imageView.image = image; 

     }); 

     [imageCache setObject:image forKey:imageName]; 
    }); 
    } 

    return cell; 
} 
+5

Questo non è completamente corretto perché se le celle vengono riutilizzate correttamente è possibile che quando viene caricata l'immagine e la cella venga aggiornata, quell'istanza della cella venga utilizzata per rappresentare un altro record nel modello. Meglio aggiornare la cache e chiamare la vista raccolta reloadItemsAtIndexPaths e ottenere cellForItemAtIndexPath per impostare l'immagine dalla cache (se è visibile). – Ants

+0

Ah, ha senso. In effetti, mi sono imbattuto in quel problema (solo una volta, ma capisco cosa intendi). Grazie! – BrianS

+0

@Ants, se è possibile aggiungere il codice, molte persone saranno beneficiate (incluso me). Grazie. – Satyam