I\'m trying to improve the performance of my image-intensive iPhone app by using a disk-based image cache instead of going over the network. I\'ve modeled my image cache after S
It's typically the image decoding which takes time, and that causes the UI to freeze (since it's all happening on the main thread). Every time you call [UIImage imageWithData:]
on a large image, you'll notice a hiccup. Decoding a smaller image is far quicker.
Two options:
didFinishScrolling
. The thumbnails should decode quickly enough such that you don't skip any frames.I prefer the second approach; it's easy enough with GDC nowadays.
You should check out the LazyTableImages sample app.
I've had this problem - you are hitting the limit of how fast the UI can load an image while scrolling - so i'd just work around the problem and improve the user experience.
The image from the disk is actually read while drawing the image on the imageview. Even if we cache the image reading from the disk it does not affect since it just keeps reference to the file. You might have to use tiling of larger images for this purpose.
Regards, Deepa
If you've narrowed it down to network activity I would try encapsulating your request to ensure it is 100% off of the main thread. While you can use NSURLConnection asynchronously and respond to it's delegate methods, I find it easier to wrap a synchronous request in a background operation. You can use NSOperation or grand central dispatch if your needs are more complex. An (relatively) simple example in an imageLoader implementation could be:
// imageLoader.m
// assumes that that imageCache uses kvp to look for images
- (UIImage *)imageForKey:(NSString *)key
{
// check if we already have the image in memory
UImage *image = [_images objectForKey:key];
// if we don't have an image:
// 1) start a background task to load an image from a file or URL
// 2) return a default image to display while loading
if (!image) {
[self performSelectorInBackground:@selector(loadImageForKey) withObject:key];
image = [self defaultImage];
}
return image;
}
- (void)loadImageForKey:(NSString *)key
{
NSAutoReleasePool *pool = [[NSAutoReleasePool alloc] init];
// attempt to load the image from the file cache
UIImage *image = [self imageFromFileForKey:key];
// if no image, load the image from the URL
if (!image) {
image = [self imageFromURLForKey:key];
}
// if no image, return default or imageNotFound image
if (!image) {
image = [self notFoundImage];
}
if ([_delegate respondsTo:@selector(imageLoader:didLoadImage:ForKey:)]) {
[_delegate imageLoader:self didLoadImage:image forKey:key];
}
[pool release];
}
- (UIImage *)imageFromURLForKey:(NSString *)key
{
NSError *error = nil;
NSData *imageData = [NSData dataWithContentsOfURL:[self imageURLForKey:key]
options:0
error:&error];
UIImage *image;
// handle error if necessary
if (error) {
image = [self errorImage];
}
// create image from data
else {
image = [UIImage imageWithData:imageData];
}
return image;
}