The best solution is always having the right image size in your UIImageView
. However, if you cannot have the correct image size and you need to resize it, another good solution is to use CoreGraphics to perform an image scale operation outside the main thread.
Since SDK 4.0, CoreGraphics operations are thread safe, so you can put all the resizing stuff into a background queue and handle the resizing in there. Once the resizing has finished, you have to assign the cropped image in your UIImageView
in the main thread because all UIKit
stuff must be done in that thread. With this approach, you're not going to block the main thread every time you resize the images.
Once you've done that, you can also cache the cropping results in order to avoid repetitive cropping calculation (i.e., every time you scroll into the same UITableViewCell
) and improve performance.
You can implement this as a UIImage
category, take my code as an example:
- (void)resizeImageWithSize:(CGSize)size
cacheKey:(NSString *)cacheKey
completionBlock:(void (^)(UIImage *croppedImage))completionBlock
{
dispatch_async([[self class] sharedBackgroundQueue], ^{
// Check if we have the image cached
UIImage *resizedImage = [[[self class] resizedImageCache] objectForKey:cacheKey];
if (nil == resizedImage) {
// If not, resize and cache it
@autoreleasepool {
resizedImage = [self resizeImageWithSize:size];
[[[self class] resizedImageCache] setObject:resizedImage forKey:cacheKey];
}
}
dispatch_async(dispatch_get_main_queue(), ^{
completionBlock(resizedImage);
});
});
}
Then, the resizeImageWithSize:
method implementation is the one where all CoreGraphics stuff happen. You may find interesting the FXImageView library by Nick Lockwood, which uses the same approach: UIImageView
category, has a resize cache and uses a background thread to do the Core Graphics stuff.