September, 2009


13
Sep 09

A simple COCOA Asynchronous image loader class to use in your iPhone app.

Updated version here : http://www.geekygoodness.com/2011/06/17/uiimage-from-url-simplified/

This isnt a tutorial, this is just some source code that you might find useful. This class will load images in the background so it wont lock your UI up!

Heres the header file :

@interface GGImageLoader : NSObject {
 
	NSURLConnection * connection;
 
	NSURL * url;
 
	NSMutableData * mutData;
 
	UIImage * image;
 
	id delegate;
 
}
 
@property ( nonatomic, retain ) UIImage * image;
 
- (id)initWithURL:(NSURL *)aURL;
- (void)setDelegate:(id)anObject;
- (void)load;
 
@end
 
@protocol GGImageLoaderProtocol
 
@required
- (void)imageLoader:(GGImageLoader *)loader
	   didLoadImage:(UIImage *)anImage;
 
@optional
- (void)imageLoader:(GGImageLoader *)loader
	didReceiveError:(NSError *)anError;
 
@end

and heres the main file :

#import "GGImageLoader.h"
 
@implementation GGImageLoader
 
@synthesize image;
 
- (void)dealloc
{
	[url release];
	[connection release];
	[mutData release];
	[image release];
        [super dealloc];
}
 
- (id)initWithURL:(NSURL *)aURL
{
	url = [aURL retain];
	return self;
}
 
- (void)setDelegate:(id)anObject
{
	delegate = anObject;
}
 
- (void)load
{
	// SHOW NETWORK INDICATOR
 
	[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
 
	// SET UP THE REQUEST
 
	NSURLRequest * request = [[[NSURLRequest alloc] initWithURL:url] autorelease];
 
	// SET UP THE CONNECTION
 
	connection = [[NSURLConnection alloc] initWithRequest:request
												 delegate:self];
 
	// NEW MUT DATA
 
	mutData = [[[NSMutableData alloc] init] retain];
 
}
 
- (void)connection:(NSURLConnection *)connection
  didFailWithError:(NSError *)error
{
	if( [delegate respondsToSelector:@selector(imageLoader:didReceieveError:)] )
	{
		[delegate imageLoader:self
			  didReceiveError:error];
	}
}
 
- (void)connection:(NSURLConnection *)connection
	didReceiveData:(NSData *)data
{
 
	// APPEND THE DATA
 
	[mutData appendData:data];
}
 
- (void)connectionDidFinishLoading:(NSURLConnection *)aConnection
{
 
	// ONCE LOADED HIDE NETWORK INDICATOR
 
	[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
 
	// RELEASE THE CONNECTION
 
	[connection release];
 
	// CREATE NEW UIIMAGE FROM THE DATA
 
	image = [[[UIImage alloc] initWithData:mutData] retain];
 
	if( [delegate respondsToSelector:@selector(imageLoader:didLoadImage:)] )
	{
		[delegate imageLoader:self
				 didLoadImage:image];
	}
 
}
 
@end

Its pretty self explanatory, meerly do the following to get it to work..

GGImageLoader * imageLoader = [[[GGImageLoader alloc] initWithURL:[NSURL URLWithString:@"myimageurlhere"]] retain];
[imageLoader setDelegate:self];
[imageLoader load];

The class also has delegate methods and a protocol to follow, so we know when the image has loaded, you can use the GGImageLoaderProtocol in your header file if you like.

- (void)imageLoader:(GGImageLoader *)imageLoader didReceieveError:(NSError *)anError
{
}
 
- (void)imageLoader:(GGImageLoader *)imageLoader didLoadImage:(UIImage *)anImage
{
	// BE SURE TO RELEASE THE IMAGE LOADER
	[imageLoader release];
}

and thats about it, hope its helps some people out!

If ive made a mistake anywhere in this please say, it was a rush post!