Objective C: Cache Image on iPhone
September 2nd, 2009
No comments
If you’re pulling in web data such as images that doesn’t change but needs to be viewed multiple times, you’ll want to cache it. Caching images dramatically improves the performance of scrolling tables and other views.
Note: this only works for JPG and PNG images. If you have suggestions or find bugs, let me know.
Utilities.h:
Code:
#import Foundation/Foundation.h @interface Utilities : NSObject { } // Methods - (void) cacheImage: (NSString *) ImageURLString; - (UIImage *) getCachedImage: (NSString *) ImageURLString; - (UIImage *) roundCorners: (UIImage*) img; @end
Utilities.m
Code:
#import "Utilities.h" #define TMP NSTemporaryDirectory() @implementation Utilities
Function to actually cache the image – checks to see if one with the same name already exists
Code:
- (void) cacheImage: (NSString *) ImageURLString { NSURL *ImageURL = [NSURL URLWithString: ImageURLString]; // Generate a unique path to a resource representing the image you want NSString *filename = [[something unique, perhaps the image name]]; NSString *uniquePath = [TMP stringByAppendingPathComponent: filename]; // Check for file existence if(![[NSFileManager defaultManager] fileExistsAtPath: uniquePath]) { // The file doesn't exist, we should get a copy of it // Fetch image NSData *data = [[NSData alloc] initWithContentsOfURL: ImageURL]; UIImage *image = [[UIImage alloc] initWithData: data]; // Do we want to round the corners? image = [self roundCorners: image]; // Is it PNG or JPG/JPEG? // Running the image representation function writes the data from the image to a file if([ImageURLString rangeOfString: @".png" options: NSCaseInsensitiveSearch].location != NSNotFound) { [UIImagePNGRepresentation(image) writeToFile: uniquePath atomically: YES]; } else if( [ImageURLString rangeOfString: @".jpg" options: NSCaseInsensitiveSearch].location != NSNotFound || [ImageURLString rangeOfString: @".jpeg" options: NSCaseInsensitiveSearch].location != NSNotFound ) { [UIImageJPEGRepresentation(image, 100) writeToFile: uniquePath atomically: YES]; } } }
Retrieve a cached file:
Code:
- (UIImage *) getCachedImage: (NSString *) ImageURLString { NSString *filename = [[something unique, perhaps the image name]]; NSString *uniquePath = [TMP stringByAppendingPathComponent: filename]; UIImage *image; // Check for a cached version if([[NSFileManager defaultManager] fileExistsAtPath: uniquePath]) { image = [UIImage imageWithContentsOfFile: uniquePath]; // this is the cached image } else { // get a new one [self cacheImage: ImageURLString]; image = [UIImage imageWithContentsOfFile: uniquePath]; } return image; }
These two functions are just to add rounded corners to an image
Code:
static void addRoundedRectToPath(CGContextRef context, CGRect rect, float ovalWidth, float ovalHeight) { float fw, fh; if (ovalWidth == 0 || ovalHeight == 0) { CGContextAddRect(context, rect); return; } CGContextSaveGState(context); CGContextTranslateCTM (context, CGRectGetMinX(rect), CGRectGetMinY(rect)); CGContextScaleCTM (context, ovalWidth, ovalHeight); fw = CGRectGetWidth (rect) / ovalWidth; fh = CGRectGetHeight (rect) / ovalHeight; CGContextMoveToPoint(context, fw, fh/2); CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1); CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1); CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1); CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1); CGContextClosePath(context); CGContextRestoreGState(context); } - (UIImage *) roundCorners: (UIImage*) img { int w = img.size.width; int h = img.size.height; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef context = CGBitmapContextCreate(NULL, w, h, 8, 4 * w, colorSpace, kCGImageAlphaPremultipliedFirst); CGContextBeginPath(context); CGRect rect = CGRectMake(0, 0, img.size.width, img.size.height); addRoundedRectToPath(context, rect, 5, 5); CGContextClosePath(context); CGContextClip(context); CGContextDrawImage(context, CGRectMake(0, 0, w, h), img.CGImage); CGImageRef imageMasked = CGBitmapContextCreateImage(context); CGContextRelease(context); CGColorSpaceRelease(colorSpace); [img release]; return [UIImage imageWithCGImage:imageMasked]; } @end