Tag Archive for 'UIImage'

Asynchronous images on iOS

The iOS SDK provides many ways to manipulate images. The simplest way is loading an Image into an UIImageView. The issue of this way is that loading the image in that way is a synchronous operations:

UIImageView *imageView = [[UIImageView alloc] initWithFrame: CGRectMake(100.0, 100.0, 57.0, 57.0)];

NSData* data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:@"image.jpg"]];

UIImage* image = [[UIImage alloc] initWithData:data];

[imageView setImage:image];

[image release];

[data release];

When you are loading many images, synchronous operations are not your best friend because it does not have a good performance. In this case you will prefer to load the images asynchronously. To do that, you can solve the situation using threads. But I want a reusable solution based on classes, so I decide to extend the UIImage to do that.

My code is based on the code of iOS Dev Tips, but instead of use an UIImageView I decide to use an UIImage. The strategy is download the image as a NSData in background and use a delegate to notify your classe. Follow the AsynchronousUIImage.h :

#import

@class AsynchronousUIImage;

@protocol AsynchronousUIImageDelegate

@optional

-(void) imageDidLoad:(AsynchronousUIImage *)anImage;

@end

@interface AsynchronousUIImage : UIImage{

NSURLConnection *connection;

NSMutableData *data;

}

@property (nonatomic, assign) id  delegate;

@property (nonatomic)  int tag;

- (void)loadImageFromURL:(NSString *)anUrl;
@end

The protocol has one optional method called imageDidLoad:(AsynchronousUIImage *)anImage so your code can be notified that the image has loaded. The interface has two properties one for the delegate and the other one is a tag to identification when the delegate is called.

So, let’s go to the implementation:

@implementation AsynchronousUIImage

@synthesize delegate;

@synthesize tag;

- (void)loadImageFromURL:(NSString *)anUrl {

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:anUrl]

cachePolicy:NSURLRequestReturnCacheDataElseLoad

timeoutInterval:30.0];

connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

}

- (void)connection:(NSURLConnection *)theConnection didReceiveData:(NSData *)incrementalData {

if (data == nil)

data = [[NSMutableData alloc] initWithCapacity:2048];

[data appendData:incrementalData];

}

- (void)connectionDidFinishLoading:(NSURLConnection *)theConnection

{

[self initWithData:data];

[data release], data = nil;

[connection release], connection = nil;

[self.delegate imageDidLoad:self];

}

-(void)dealloc{

[super dealloc];

connection = nil;

data = nil;

}

In the loadImageFromURL method we use NSURLConnection to get the data from the web then in the didReceiveData method we get the pieces of data and finally in the connectionDidFinishLoading method we set the data to the UIImage object, do the memory management and call the delegate method.

So, you can use AsynchronousUIImage class that way:

AsynchronousUIImage *image = [[AsynchronousUIImage alloc] init];

[image loadImageFromURL: @"http://yourimage" ];

image.tag = 1;

image.delegate = self;

[image release];

And then implement the imageDidLoad delegate method that way:

-(void) imageDidLoad:(AsynchronousUIImage *)anImage{

 if (anImage.tag == 1) {

 myImageView.image = anImage;

 }

}

You can find a complete example in: https://github.com/gazolla/AsyncImageTest




Premium Wordpress Plugin