Refactoring image request API to remove unnecessary configuration, and focus the design goals of those classes

This commit is contained in:
Mattt Thompson 2011-09-16 22:40:52 -05:00
parent 686854b8da
commit 50014afa22
6 changed files with 74 additions and 87 deletions

View file

@ -28,12 +28,10 @@
+ (id)sharedImageCache; + (id)sharedImageCache;
- (UIImage *)cachedImageForRequest:(NSURLRequest *)urlRequest - (UIImage *)cachedImageForRequest:(NSURLRequest *)urlRequest
imageSize:(CGSize)imageSize cacheName:(NSString *)cacheName;
options:(AFImageRequestOptions)options;
- (void)cacheImage:(UIImage *)image - (void)cacheImage:(UIImage *)image
forRequest:(NSURLRequest *)urlRequest forRequest:(NSURLRequest *)urlRequest
imageSize:(CGSize)imageSize cacheName:(NSString *)cacheName;
options:(AFImageRequestOptions)options;
@end @end

View file

@ -22,8 +22,8 @@
#import "AFImageCache.h" #import "AFImageCache.h"
static inline NSString * AFImageCacheKey(NSURLRequest *urlRequest, CGSize imageSize, AFImageRequestOptions options) { static inline NSString * AFImageCacheKey(NSURLRequest *urlRequest, NSString *cacheName) {
return [[[urlRequest URL] absoluteString] stringByAppendingFormat:@"#%fx%f:%d", imageSize.width, imageSize.height, options]; return [[[urlRequest URL] absoluteString] stringByAppendingFormat:@"#%@", cacheName];
} }
@implementation AFImageCache @implementation AFImageCache
@ -40,22 +40,20 @@ static inline NSString * AFImageCacheKey(NSURLRequest *urlRequest, CGSize imageS
} }
- (UIImage *)cachedImageForRequest:(NSURLRequest *)urlRequest - (UIImage *)cachedImageForRequest:(NSURLRequest *)urlRequest
imageSize:(CGSize)imageSize cacheName:(NSString *)cacheName
options:(AFImageRequestOptions)options
{ {
return [self objectForKey:AFImageCacheKey(urlRequest, imageSize, options)]; return [self objectForKey:AFImageCacheKey(urlRequest, cacheName)];
} }
- (void)cacheImage:(UIImage *)image - (void)cacheImage:(UIImage *)image
forRequest:(NSURLRequest *)urlRequest forRequest:(NSURLRequest *)urlRequest
imageSize:(CGSize)imageSize cacheName:(NSString *)cacheName
options:(AFImageRequestOptions)options
{ {
if (!image) { if (!image) {
return; return;
} }
[self setObject:image forKey:AFImageCacheKey(urlRequest, imageSize, options)]; [self setObject:image forKey:AFImageCacheKey(urlRequest, cacheName)];
} }
@end @end

View file

@ -24,19 +24,15 @@
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import "AFHTTPRequestOperation.h" #import "AFHTTPRequestOperation.h"
typedef enum {
AFImageRequestDefaultOptions = 0,
AFImageRequestRoundCorners = 1 << 1,
} AFImageRequestOptions;
@interface AFImageRequestOperation : AFHTTPRequestOperation @interface AFImageRequestOperation : AFHTTPRequestOperation
+ (id)operationWithRequest:(NSURLRequest *)urlRequest + (id)operationWithRequest:(NSURLRequest *)urlRequest
success:(void (^)(UIImage *image))success; success:(void (^)(UIImage *image))success;
+ (id)operationWithRequest:(NSURLRequest *)urlRequest + (id)operationWithRequest:(NSURLRequest *)urlRequest
imageSize:(CGSize)imageSize imageProcessingBlock:(UIImage *(^)(UIImage *))imageProcessingBlock
options:(AFImageRequestOptions)options cacheName:(NSString *)cacheNameOrNil
success:(void (^)(UIImage *image))success; success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success
failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure;
@end @end

View file

@ -25,14 +25,6 @@
#import "UIImage+AFNetworking.h" #import "UIImage+AFNetworking.h"
static CGFloat const kAFImageRequestJPEGQuality = 0.8;
static NSUInteger const kAFImageRequestMaximumResponseSize = 8 * 1024 * 1024;
static inline CGSize kAFImageRequestRoundedCornerRadii(CGSize imageSize) {
CGFloat dimension = fmaxf(imageSize.width, imageSize.height) * 0.1;
return CGSizeMake(dimension, dimension);
}
static dispatch_queue_t af_image_request_operation_processing_queue; static dispatch_queue_t af_image_request_operation_processing_queue;
static dispatch_queue_t image_request_operation_processing_queue() { static dispatch_queue_t image_request_operation_processing_queue() {
if (af_image_request_operation_processing_queue == NULL) { if (af_image_request_operation_processing_queue == NULL) {
@ -47,42 +39,48 @@ static dispatch_queue_t image_request_operation_processing_queue() {
+ (id)operationWithRequest:(NSURLRequest *)urlRequest + (id)operationWithRequest:(NSURLRequest *)urlRequest
success:(void (^)(UIImage *image))success success:(void (^)(UIImage *image))success
{ {
return [self operationWithRequest:urlRequest imageSize:CGSizeZero options:AFImageRequestDefaultOptions success:success]; return [self operationWithRequest:urlRequest imageProcessingBlock:nil cacheName:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
if (success) {
success(image);
}
} failure:nil];
} }
+ (id)operationWithRequest:(NSURLRequest *)urlRequest + (id)operationWithRequest:(NSURLRequest *)urlRequest
imageSize:(CGSize)imageSize imageProcessingBlock:(UIImage *(^)(UIImage *))imageProcessingBlock
options:(AFImageRequestOptions)options cacheName:(NSString *)cacheNameOrNil
success:(void (^)(UIImage *image))success success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success
failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure
{ {
AFImageRequestOperation *operation = [self operationWithRequest:urlRequest completion:^(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data, NSError *error) { AFImageRequestOperation *operation = [self operationWithRequest:urlRequest completion:^(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data, NSError *error) {
dispatch_async(image_request_operation_processing_queue(), ^(void) { dispatch_async(image_request_operation_processing_queue(), ^(void) {
UIImage *image = nil; if (error) {
if ([[UIScreen mainScreen] scale] == 2.0) { if (failure) {
CGImageRef imageRef = [[UIImage imageWithData:data] CGImage]; failure(request, response, error);
image = [UIImage imageWithCGImage:imageRef scale:2.0 orientation:UIImageOrientationUp];
} else {
image = [UIImage imageWithData:data];
}
if (!(CGSizeEqualToSize(image.size, imageSize) || CGSizeEqualToSize(imageSize, CGSizeZero))) {
image = [UIImage imageByScalingAndCroppingImage:image size:imageSize];
}
if ((options & AFImageRequestRoundCorners)) {
image = [UIImage imageByRoundingCornersOfImage:image corners:UIRectCornerAllCorners cornerRadii:kAFImageRequestRoundedCornerRadii(image.size)];
}
dispatch_sync(dispatch_get_main_queue(), ^(void) {
if (success) {
success(image);
} }
}); } else {
UIImage *image = nil;
[[AFImageCache sharedImageCache] cacheImage:image forRequest:request imageSize:imageSize options:options]; if ([[UIScreen mainScreen] scale] == 2.0) {
CGImageRef imageRef = [[UIImage imageWithData:data] CGImage];
image = [UIImage imageWithCGImage:imageRef scale:2.0 orientation:UIImageOrientationUp];
} else {
image = [UIImage imageWithData:data];
}
if (imageProcessingBlock) {
image = imageProcessingBlock(image);
}
dispatch_sync(dispatch_get_main_queue(), ^(void) {
if (success) {
success(request, response, image);
}
});
[[AFImageCache sharedImageCache] cacheImage:image forRequest:request cacheName:cacheNameOrNil];
}
}); });
}]; }];
operation.runLoopModes = [NSSet setWithObject:NSRunLoopCommonModes];
return operation; return operation;
} }

View file

@ -32,14 +32,7 @@
- (void)setImageWithURL:(NSURL *)url - (void)setImageWithURL:(NSURL *)url
placeholderImage:(UIImage *)placeholderImage placeholderImage:(UIImage *)placeholderImage
imageSize:(CGSize)imageSize success:(void (^)(UIImage *image, BOOL cacheUsed))block;
options:(AFImageRequestOptions)options;
- (void)setImageWithURL:(NSURL *)url
placeholderImage:(UIImage *)placeholderImage
imageSize:(CGSize)imageSize
options:(AFImageRequestOptions)options
block:(void (^)(UIImage *image, BOOL cacheUsed))block;
- (void)cancelImageRequestOperation; - (void)cancelImageRequestOperation;

View file

@ -24,6 +24,7 @@
#import <objc/runtime.h> #import <objc/runtime.h>
#import "UIImageView+AFNetworking.h" #import "UIImageView+AFNetworking.h"
#import "UIImage+AFNetworking.h"
#import "AFImageCache.h" #import "AFImageCache.h"
@ -54,37 +55,27 @@ static NSString * const kUIImageViewImageRequestObjectKey = @"_af_imageRequestOp
if (!_imageRequestOperationQueue) { if (!_imageRequestOperationQueue) {
_imageRequestOperationQueue = [[NSOperationQueue alloc] init]; _imageRequestOperationQueue = [[NSOperationQueue alloc] init];
[_imageRequestOperationQueue setMaxConcurrentOperationCount:6]; [_imageRequestOperationQueue setMaxConcurrentOperationCount:8];
} }
return _imageRequestOperationQueue; return _imageRequestOperationQueue;
} }
#pragma mark - #pragma mark -
- (void)setImageWithURL:(NSURL *)url { - (void)setImageWithURL:(NSURL *)url {
[self setImageWithURL:url placeholderImage:nil]; [self setImageWithURL:url placeholderImage:nil];
} }
- (void)setImageWithURL:(NSURL *)url - (void)setImageWithURL:(NSURL *)url
placeholderImage:(UIImage *)placeholderImage placeholderImage:(UIImage *)placeholderImage
{ {
[self setImageWithURL:url placeholderImage:placeholderImage imageSize:self.frame.size options:AFImageRequestDefaultOptions]; [self setImageWithURL:url placeholderImage:placeholderImage success:nil];
} }
- (void)setImageWithURL:(NSURL *)url - (void)setImageWithURL:(NSURL *)url
placeholderImage:(UIImage *)placeholderImage placeholderImage:(UIImage *)placeholderImage
imageSize:(CGSize)imageSize success:(void (^)(UIImage *image, BOOL cacheUsed))success
options:(AFImageRequestOptions)options
{
[self setImageWithURL:url placeholderImage:placeholderImage imageSize:imageSize options:options block:nil];
}
- (void)setImageWithURL:(NSURL *)url
placeholderImage:(UIImage *)placeholderImage
imageSize:(CGSize)imageSize
options:(AFImageRequestOptions)options
block:(void (^)(UIImage *image, BOOL cacheUsed))block
{ {
if (!url || [url isEqual:self.imageRequestOperation.request.URL]) { if (!url || [url isEqual:self.imageRequestOperation.request.URL]) {
return; return;
@ -96,30 +87,43 @@ static NSString * const kUIImageViewImageRequestObjectKey = @"_af_imageRequestOp
[request setHTTPShouldHandleCookies:NO]; [request setHTTPShouldHandleCookies:NO];
[request setHTTPShouldUsePipelining:YES]; [request setHTTPShouldUsePipelining:YES];
UIImage *cachedImage = [[AFImageCache sharedImageCache] cachedImageForRequest:request imageSize:imageSize options:options]; NSString *cacheName = @"UIImageView";
if (placeholderImage) {
cacheName = [cacheName stringByAppendingFormat:@"(%@)", NSStringFromCGSize(placeholderImage.size)];
}
UIImage *cachedImage = [[AFImageCache sharedImageCache] cachedImageForRequest:request cacheName:cacheName];
if (cachedImage) { if (cachedImage) {
self.image = cachedImage; self.image = cachedImage;
if (block) { if (success) {
block(cachedImage, YES); success(cachedImage, YES);
} }
} else { } else {
self.image = placeholderImage; self.image = placeholderImage;
self.imageRequestOperation = [AFImageRequestOperation operationWithRequest:request imageSize:imageSize options:options success:^(UIImage *image) { self.imageRequestOperation = [AFImageRequestOperation operationWithRequest:request imageProcessingBlock:^UIImage *(UIImage *image) {
if (placeholderImage) {
image = [UIImage imageByScalingAndCroppingImage:image size:placeholderImage.size];
}
return image;
} cacheName:cacheName success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
if (self.imageRequestOperation && ![self.imageRequestOperation isCancelled]) { if (self.imageRequestOperation && ![self.imageRequestOperation isCancelled]) {
if (block) { if (success) {
block(image, NO); success(image, NO);
} }
if ([[request URL] isEqual:[[self.imageRequestOperation request] URL]]) { if ([[request URL] isEqual:[[self.imageRequestOperation request] URL]]) {
self.image = image; self.image = image;
} else { } else {
self.image = placeholderImage; self.image = placeholderImage;
} }
} }
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
self.imageRequestOperation = nil;
}]; }];
[[[self class] sharedImageRequestOperationQueue] addOperation:self.imageRequestOperation]; [[[self class] sharedImageRequestOperationQueue] addOperation:self.imageRequestOperation];
} }
} }