Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I wrote this (with concepts and some code taken from Lane Roathe's excellent UIImageView+Cache category) for an app I've been working on. It uses the <a href="http://allseeing-i.com/ASIHTTPRequest/" rel="nofollow" title="ASIHTTPRequest">ASIHTTPRequest</a> classes as well, which are great. This could definitely be improved.. for example, by allowing requests to be canceled if no longer needed, or by utilizing the notification userInfo to allow for more precise UI updating.. but it's working well for my purposes.</p> <pre><code>@implementation ImageFetcher #define MAX_CACHED_IMAGES 20 static NSMutableDictionary* cache = nil; + (void)asyncImageFetch:(UIImage**)anImagePtr withURL:(NSURL*)aUrl { if(!cache) { cache = [[NSMutableDictionary dictionaryWithCapacity:MAX_CACHED_IMAGES] retain]; } UIImage* newImage = [cache objectForKey:aUrl.description]; if(!newImage) { // cache miss - doh! ASIHTTPRequest *imageRequest = [ASIHTTPRequest requestWithURL:aUrl]; imageRequest.userInfo = [NSDictionary dictionaryWithObject:[NSValue valueWithPointer:anImagePtr] forKey:@"imagePtr"]; imageRequest.delegate = self; [imageRequest setDidFinishSelector:@selector(didReceiveImage:)]; [imageRequest setDidFailSelector:@selector(didNotReceiveImage:)]; [imageRequest startAsynchronous]; } else { // cache hit - good! *anImagePtr = [newImage retain]; } } + (void)didReceiveImage:(ASIHTTPRequest *)request { NSLog(@"Image data received."); UIImage **anImagePtr = [(NSValue*)[request.userInfo objectForKey:@"imagePtr"] pointerValue]; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; UIImage *newImage = [[UIImage imageWithData:[request responseData]] retain]; if(!newImage) { NSLog(@"UIImageView: LoadImage Failed"); } else { *anImagePtr = newImage; // check to see if we should flush existing cached items before adding this new item if( [cache count] &gt;= MAX_CACHED_IMAGES) [cache removeAllObjects]; [cache setValue:newImage forKey:[request url].description]; NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; [nc postNotificationName: @"ImageDidLoad" object: self userInfo:request.userInfo]; } [pool drain]; } </code></pre> <p>You call this code as follows:</p> <pre><code>[ImageFetcher asyncImageFetch:&amp;icon withURL:url]; </code></pre> <p>I'm also using notifications, for better or worse, to let any owners of the corresponding UIImage know when they should redisplay- in this case, it's in a tableView context:</p> <pre><code>- (void)viewDidLoad { [super viewDidLoad]; NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; [nc addObserver:self selector:@selector(imageDidLoad:) name:@"ImageDidLoad" object:nil]; } - (void)imageDidLoad:(NSNotification*)notif { NSLog(@"Received icon load notification."); // reload table view so that new image appears.. would be better if I could // only reload the particular UIImageView that holds this image, oh well... [self.tableView reloadData]; } - (void)dealloc { NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; [nc removeObserver:self]; // ... } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload