Skip to content

Instantly share code, notes, and snippets.

@a-square
Last active August 29, 2015 14:05
Show Gist options
  • Save a-square/1b6280e833f032ec08ba to your computer and use it in GitHub Desktop.
Save a-square/1b6280e833f032ec08ba to your computer and use it in GitHub Desktop.
More responsive UIImageView+AFNetworking using NSURLCache
// It's debatable if it's actually a good idea, because most of the time the image will be
// loaded from the cache without revalidation anyway, but it still has some utility in cases
// when max-age is short, or the image is big
//
// Also, it is more useful if we assume that max-age is smaller than the average user session,
// and that the iOS device never has to evict the images in the UIImageView+AFNetworking cache,
// because then *every* request for the image that actually goes through the NSURLCache will
// trigger the double request codepath. That being said, it's still probably excessive, because
// the amortised delay before the image is shown is still not affected much
- (void)setImageWithURLRequest:(NSURLRequest *)originalURLRequest
placeholderImage:(UIImage *)placeholderImage
success:(void (^)(NSURLRequest *, NSHTTPURLResponse *, UIImage *))success
failure:(void (^)(NSURLRequest *, NSHTTPURLResponse *, NSError *))failure
{
__weak __typeof(self) weakSelf = self;
// first, try to find the image in the cache (both NSURLCache and UIImageView+AFNetworking caches)
NSMutableURLRequest *cacheOnlyURLRequest = [originalURLRequest mutableCopy];
cacheOnlyURLRequest.cachePolicy = NSURLRequestReturnCacheDataDontLoad;
[self
superSetImageWithURLRequest:cacheOnlyURLRequest
placeholderImage:placeholderImage
// found the image in the cache
success:^void(NSURLRequest *urlRequest, NSHTTPURLResponse *urlResponse, UIImage *image) {
__typeof(self) strongSelf = weakSelf;
if (!strongSelf) {
return;
}
if (!urlResponse) {
// the image was in the UIImageView+AFNetworking cache,
// so we should just use it to avoid excessive network traffic
return;
}
// kill the image in the UIImageView+AFNetworking cache so that the next HTTP request
// goes through NSURLConnection
// WARNING: assumes that +sharedImageCache is actually an NSCache instance!
[(NSCache *)[[super class] sharedImageCache] removeObjectForKey:[[urlRequest URL] absoluteString]];
// repeat the request, but now allow NSURLCache to revalidate it if needed
// use the previously received image as a placeholder
[strongSelf superSetImageWithURLRequest:originalURLRequest placeholderImage:image success:success failure:failure];
}
// image not found in the cache
failure:^void(NSURLRequest *urlRequest, NSHTTPURLResponse *urlResponse, NSError *error) {
// default behavior
[weakSelf superSetImageWithURLRequest:originalURLRequest placeholderImage:placeholderImage success:success failure:failure];
}];
}
// a trick to avoid implicitly retaining self when using super
- (void)superSetImageWithURLRequest:(NSURLRequest *)urlRequest
placeholderImage:(UIImage *)placeholderImage
success:(void (^)(NSURLRequest *, NSHTTPURLResponse *, UIImage *))success
failure:(void (^)(NSURLRequest *, NSHTTPURLResponse *, NSError *))failure
{
[super setImageWithURLRequest:urlRequest placeholderImage:placeholderImage success:success failure:failure];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment