I'm pretty new to Objective-C so hopefully this all makes sense. I've downloaded images from a server and have displayed them in an image view in the collectionView cellForItemAtIndexPath:
method. The issue I'm facing is that the images don't appear to be caching. It looks like each time a cell is being reused, the associated image from the server is being re-downloaded.
In my viewDidLoad method I'm creating a NSMutableDictionary:
imageDictionary = [[NSMutableDictionary alloc]initWithCapacity:50.0];
From reading the documentation and looking at answers to similar questions I thought that this, plus the following code would be enough. I've been at this for a couple of days and I know there is something I'm missing or a concept I'm not grasping.
#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;
}
Any help would be greatly appreciated. Thanks in advance.
Image caching essentially means downloading an image to the local storage in the app's cache directory (or any other directory that is accessible to the app) and loading it from local storage next time the image loads.
Cache is a hardware or software component that stores data so future requests for that data can be served faster; the data stored in a cache might be the result of an earlier computation, or the duplicate of data stored elsewhere.
One more thing about NSCache is, it is thread safe. We can access it from any thread without worrying about managing threads while accessing NSCache. You can set & get name for cache. The default value is an empty string (“”).
An object that manages image data in your app.
@yuf - thanks again for the direction. NSCache seems to be getting me the results I was after. Here is the code that is working properly. If anyone has a similar issue, you can compare the following to my original question.
- (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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With