Ad

Our DNA is written in Swift
Jump

A Quick Lazy-Loading UIImageView

In case you ever need to enhance UIImageView to load it’s image lazily… like if it’s coming from a web URL.

I used this on my NSAttributedStrings+HTML open source project to improve performance and also be able to have images that are not available locally. But you don’t want to do a synchronous call over the web, that would block your UI.

I admit, it’s a quickie, but hey, sometimes those are also fun!

DTLazyImageView.h

@interface DTLazyImageView : UIImageView 
{
	NSURL *_url;
 
	BOOL _loading;
}
 
@property (nonatomic, retain) NSURL *url;
 
@end

DTLazyImageView.m

#import "DTLazyImageView.h"
 
@implementation DTLazyImageView
 
- (void)dealloc
{
	self.image = nil;
	[_url release];
 
	[super dealloc];
}
 
- (void)loadImageAtURL:(NSURL *)url
{
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 
	NSData *data = [[NSData alloc] initWithContentsOfURL:url];
 
	if (data)
	{
		UIImage *image = [[UIImage alloc] initWithData:data];
 
		[self performSelectorOnMainThread:@selector(setImage:) withObject:image 
				waitUntilDone:YES];
 
		[image release];
	}
 
	[data release];
 
	_loading = NO;
 
	[pool release];
}
 
- (void)didMoveToSuperview
{
	if (!self.image && _url && !_loading)
	{
		_loading = YES;
		[self performSelectorInBackground:@selector(loadImageAtURL:) withObject:_url];
	}	
}
 
#pragma mark Properties
 
@synthesize url = _url;
 
@end

You can see, it’s very simple. When the view is added to a super view by means of addSubview then it starts loading the image on a background thread. Setting the image has to occur on the main thread because UIKit is not threadsafe, or at least has not been until recently.


Categories: Recipes

4 Comments »

  1. This is simple and clean, which is great. But be aware of one key drawback: you can’t cancel the loading of this image, since it is impossible to safely “kill” background threads. If the server takes a long time to respond, the background thread will continue running until it times out.

    So I wouldn’t advise using this for situations like loading images in table view cells while scrolling, or else you’ll end up with lots of accumulated background threads waiting to finish.

    Instead, consider using an asynchronous, cancellable NSURLConnection to load your image.