First implementation of protocol for AFHTTPClient to register classes to automatically determine the appropriate operation to create
Wrapping AFURLConnectionOperation -setCompletionBlock: with blockSelf release pattern to avoid retain cycle
This commit is contained in:
parent
2c478758a2
commit
c2be31d4fa
@ -49,6 +49,7 @@
|
||||
@private
|
||||
NSURL *_baseURL;
|
||||
NSStringEncoding _stringEncoding;
|
||||
NSMutableArray *_registeredHTTPOperationClassNames;
|
||||
NSMutableDictionary *_defaultHeaders;
|
||||
NSOperationQueue *_operationQueue;
|
||||
}
|
||||
@ -96,6 +97,12 @@
|
||||
*/
|
||||
- (id)initWithBaseURL:(NSURL *)url;
|
||||
|
||||
///----------------------------------
|
||||
/// @name Managing HTTP Operations
|
||||
///----------------------------------
|
||||
|
||||
- (BOOL)registerHTTPOperationClass:(Class)operationClass;
|
||||
|
||||
///----------------------------------
|
||||
/// @name Managing HTTP Header Values
|
||||
///----------------------------------
|
||||
|
||||
@ -77,6 +77,7 @@ static NSString * AFURLEncodedStringFromStringWithEncoding(NSString *string, NSS
|
||||
|
||||
@interface AFHTTPClient ()
|
||||
@property (readwrite, nonatomic, retain) NSURL *baseURL;
|
||||
@property (readwrite, nonatomic, retain) NSMutableArray *registeredHTTPOperationClassNames;
|
||||
@property (readwrite, nonatomic, retain) NSMutableDictionary *defaultHeaders;
|
||||
@property (readwrite, nonatomic, retain) NSOperationQueue *operationQueue;
|
||||
@end
|
||||
@ -84,6 +85,7 @@ static NSString * AFURLEncodedStringFromStringWithEncoding(NSString *string, NSS
|
||||
@implementation AFHTTPClient
|
||||
@synthesize baseURL = _baseURL;
|
||||
@synthesize stringEncoding = _stringEncoding;
|
||||
@synthesize registeredHTTPOperationClassNames = _registeredHTTPOperationClassNames;
|
||||
@synthesize defaultHeaders = _defaultHeaders;
|
||||
@synthesize operationQueue = _operationQueue;
|
||||
|
||||
@ -101,6 +103,8 @@ static NSString * AFURLEncodedStringFromStringWithEncoding(NSString *string, NSS
|
||||
|
||||
self.stringEncoding = NSUTF8StringEncoding;
|
||||
|
||||
self.registeredHTTPOperationClassNames = [NSMutableArray array];
|
||||
|
||||
self.defaultHeaders = [NSMutableDictionary dictionary];
|
||||
|
||||
// Accept HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
|
||||
@ -124,11 +128,28 @@ static NSString * AFURLEncodedStringFromStringWithEncoding(NSString *string, NSS
|
||||
|
||||
- (void)dealloc {
|
||||
[_baseURL release];
|
||||
[_registeredHTTPOperationClassNames release];
|
||||
[_defaultHeaders release];
|
||||
[_operationQueue release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (BOOL)registerHTTPOperationClass:(Class)operationClass {
|
||||
if (![operationClass conformsToProtocol:@protocol(AFHTTPClientOperation)]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSString *className = NSStringFromClass(operationClass);
|
||||
[self.registeredHTTPOperationClassNames removeObject:className];
|
||||
[self.registeredHTTPOperationClassNames insertObject:className atIndex:0];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (NSString *)defaultValueForHeader:(NSString *)header {
|
||||
return [self.defaultHeaders valueForKey:header];
|
||||
}
|
||||
@ -228,16 +249,16 @@ static NSString * AFURLEncodedStringFromStringWithEncoding(NSString *string, NSS
|
||||
success:(void (^)(id object))success
|
||||
failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure
|
||||
{
|
||||
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:urlRequest success:^(__unused NSURLRequest *request, __unused NSHTTPURLResponse *response, id JSON) {
|
||||
if (success) {
|
||||
success(JSON);
|
||||
AFHTTPRequestOperation *operation = nil;
|
||||
NSString *className = nil;
|
||||
NSEnumerator *enumerator = [self.registeredHTTPOperationClassNames reverseObjectEnumerator];
|
||||
while (!operation && (className = [enumerator nextObject])) {
|
||||
Class class = NSClassFromString(className);
|
||||
if (class && [class canProcessRequest:urlRequest]) {
|
||||
operation = [class HTTPRequestOperationWithRequest:urlRequest success:success failure:failure];
|
||||
}
|
||||
} failure:^(__unused NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
|
||||
if (failure) {
|
||||
failure(response, error);
|
||||
}
|
||||
}];
|
||||
|
||||
}
|
||||
|
||||
[self.operationQueue addOperation:operation];
|
||||
}
|
||||
|
||||
|
||||
@ -23,9 +23,12 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "AFURLConnectionOperation.h"
|
||||
|
||||
@protocol AFHTTPClientRequestOperation
|
||||
+ (BOOL)canInitWithRequest:(NSURLRequest *)request;
|
||||
@protocol AFHTTPClientOperation <NSObject>
|
||||
+ (BOOL)canProcessRequest:(NSURLRequest *)request;
|
||||
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request;
|
||||
+ (id)HTTPRequestOperationWithRequest:(NSURLRequest *)urlRequest
|
||||
success:(void (^)(id object))success
|
||||
failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure;
|
||||
@end
|
||||
|
||||
/**
|
||||
@ -59,7 +62,7 @@
|
||||
@see NSOperation
|
||||
@see NSURLConnection
|
||||
*/
|
||||
@interface AFHTTPRequestOperation : AFURLConnectionOperation {
|
||||
@interface AFHTTPRequestOperation : AFURLConnectionOperation <AFHTTPClientOperation> {
|
||||
@private
|
||||
NSIndexSet *_acceptableStatusCodes;
|
||||
NSSet *_acceptableContentTypes;
|
||||
@ -80,9 +83,9 @@
|
||||
/// @name Creating HTTP Request Operations
|
||||
///---------------------------------------
|
||||
|
||||
+ (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)urlRequest
|
||||
success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data))success
|
||||
failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure;
|
||||
//+ (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)urlRequest
|
||||
// success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data))success
|
||||
// failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure;
|
||||
|
||||
///-------------------------------
|
||||
/// @name Validating HTTP Response
|
||||
|
||||
@ -31,34 +31,6 @@
|
||||
@synthesize acceptableContentTypes = _acceptableContentTypes;
|
||||
@synthesize error = _HTTPError;
|
||||
|
||||
+ (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)urlRequest
|
||||
success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data))success
|
||||
failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure
|
||||
{
|
||||
AFHTTPRequestOperation *operation = [[[self alloc] initWithRequest:urlRequest] autorelease];
|
||||
operation.completionBlock = ^ {
|
||||
if ([operation isCancelled]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (operation.error) {
|
||||
if (failure) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^(void) {
|
||||
failure(operation.request, operation.response, operation.error);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (success) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^(void) {
|
||||
success(operation.request, operation.response, operation.responseData);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return operation;
|
||||
}
|
||||
|
||||
- (id)initWithRequest:(NSURLRequest *)request {
|
||||
self = [super initWithRequest:request];
|
||||
if (!self) {
|
||||
@ -108,4 +80,42 @@
|
||||
return !self.acceptableContentTypes || [self.acceptableContentTypes containsObject:[self.response MIMEType]];
|
||||
}
|
||||
|
||||
#pragma mark - AFHTTPClientOperation
|
||||
|
||||
+ (BOOL)canProcessRequest:(NSURLRequest *)request {
|
||||
return NO;
|
||||
}
|
||||
|
||||
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
|
||||
return request;
|
||||
}
|
||||
|
||||
+ (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)urlRequest
|
||||
success:(void (^)(id object))success
|
||||
failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure
|
||||
{
|
||||
AFHTTPRequestOperation *operation = [[[self alloc] initWithRequest:urlRequest] autorelease];
|
||||
operation.completionBlock = ^ {
|
||||
if ([operation isCancelled]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (operation.error) {
|
||||
if (failure) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^(void) {
|
||||
failure(operation.response, operation.error);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (success) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^(void) {
|
||||
success(operation.responseData);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return operation;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -122,4 +122,27 @@ static dispatch_queue_t image_request_operation_processing_queue() {
|
||||
return _responseImage;
|
||||
}
|
||||
|
||||
#pragma mark - AFHTTPClientOperation
|
||||
|
||||
+ (BOOL)canProcessRequest:(NSURLRequest *)request {
|
||||
NSSet *acceptableContentTypes = [NSSet setWithObjects:@"image/tiff", @"image/jpeg", @"image/gif", @"image/png", @"image/ico", @"image/x-icon" @"image/bmp", @"image/x-bmp", @"image/x-xbitmap", @"image/x-win-bitmap", nil];
|
||||
NSSet *acceptablePathExtensions = [NSSet setWithObjects:@"tif", @"tiff", @"jpg", @"jpeg", @"gif", @"png", @"ico", @"bmp", @"cur", nil];
|
||||
return [acceptableContentTypes containsObject:[request valueForHTTPHeaderField:@"Accept"]] || [acceptablePathExtensions containsObject:[[request URL] pathExtension]];
|
||||
}
|
||||
|
||||
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
|
||||
return request;
|
||||
}
|
||||
|
||||
+ (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)urlRequest
|
||||
success:(void (^)(id object))success
|
||||
failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure
|
||||
{
|
||||
return [self imageRequestOperationWithRequest:urlRequest imageProcessingBlock:nil cacheName:nil success:^(NSURLRequest __unused *request, NSHTTPURLResponse __unused *response, UIImage *image) {
|
||||
success(image);
|
||||
} failure:^(NSURLRequest __unused *request, NSHTTPURLResponse *response, NSError *error) {
|
||||
failure(response, error);
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -120,4 +120,26 @@ static dispatch_queue_t json_request_operation_processing_queue() {
|
||||
return _responseJSON;
|
||||
}
|
||||
|
||||
#pragma mark - AFHTTPClientOperation
|
||||
|
||||
+ (BOOL)canProcessRequest:(NSURLRequest *)request {
|
||||
NSSet *acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"application/x-javascript", @"text/javascript", @"text/x-javascript", @"text/x-json", @"text/json", @"text/plain", nil];
|
||||
return [acceptableContentTypes containsObject:[request valueForHTTPHeaderField:@"Accept"]] || [[[request URL] pathExtension] isEqualToString:@"json"];
|
||||
}
|
||||
|
||||
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
|
||||
return request;
|
||||
}
|
||||
|
||||
+ (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)urlRequest
|
||||
success:(void (^)(id object))success
|
||||
failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure
|
||||
{
|
||||
return [self JSONRequestOperationWithRequest:urlRequest success:^(NSURLRequest __unused *request, NSHTTPURLResponse __unused *response, id JSON) {
|
||||
success(JSON);
|
||||
} failure:^(NSURLRequest __unused *request, NSHTTPURLResponse *response, NSError *error) {
|
||||
failure(response, error);
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -113,4 +113,26 @@ static dispatch_queue_t property_list_request_operation_processing_queue() {
|
||||
return _responsePropertyList;
|
||||
}
|
||||
|
||||
#pragma mark - AFHTTPClientOperation
|
||||
|
||||
+ (BOOL)canProcessRequest:(NSURLRequest *)request {
|
||||
NSSet *acceptableContentTypes = [NSSet setWithObjects:@"application/x-plist", @"application/xml", nil];
|
||||
return [acceptableContentTypes containsObject:[request valueForHTTPHeaderField:@"Accept"]] || [[[request URL] pathExtension] isEqualToString:@"plist"];
|
||||
}
|
||||
|
||||
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
|
||||
return request;
|
||||
}
|
||||
|
||||
+ (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)urlRequest
|
||||
success:(void (^)(id object))success
|
||||
failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure
|
||||
{
|
||||
return [self propertyListRequestOperationWithRequest:urlRequest success:^(NSURLRequest __unused *request, NSHTTPURLResponse __unused *response, id propertyList) {
|
||||
success(propertyList);
|
||||
} failure:^(NSURLRequest __unused *request, NSHTTPURLResponse *response, NSError *error) {
|
||||
failure(response, error);
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -142,6 +142,18 @@ static inline NSString * AFKeyPathFromOperationState(AFOperationState state) {
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)setCompletionBlock:(void (^)(void))block {
|
||||
if (!block) {
|
||||
[super setCompletionBlock:nil];
|
||||
}
|
||||
|
||||
__block id _blockSelf = [self retain];
|
||||
[super setCompletionBlock:^ {
|
||||
block();
|
||||
[_blockSelf autorelease];
|
||||
}];
|
||||
}
|
||||
|
||||
- (NSInputStream *)inputStream {
|
||||
return self.request.HTTPBodyStream;
|
||||
}
|
||||
@ -194,8 +206,6 @@ static inline NSString * AFKeyPathFromOperationState(AFOperationState state) {
|
||||
switch (state) {
|
||||
case AFHTTPOperationExecutingState:
|
||||
return YES;
|
||||
case AFHTTPOperationFinishedState:
|
||||
return [self isCancelled];
|
||||
default:
|
||||
return NO;
|
||||
}
|
||||
|
||||
@ -78,7 +78,7 @@ static NSString * const kAFImageRequestOperationObjectKey = @"_af_imageRequestOp
|
||||
|
||||
- (void)setImageWithURLRequest:(NSURLRequest *)urlRequest
|
||||
placeholderImage:(UIImage *)placeholderImage
|
||||
success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response,UIImage *image))success
|
||||
success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success
|
||||
failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure
|
||||
{
|
||||
if (![urlRequest URL] || (![self.af_imageRequestOperation isCancelled] && [[urlRequest URL] isEqual:self.af_imageRequestOperation.request.URL])) {
|
||||
|
||||
@ -233,12 +233,12 @@
|
||||
F874B5C913E0AA6500B28E3E /* AFHTTPRequestOperation.m */,
|
||||
F874B5D413E0AA6500B28E3E /* AFJSONRequestOperation.h */,
|
||||
F874B5CC13E0AA6500B28E3E /* AFJSONRequestOperation.m */,
|
||||
F8F4B16C143CD1410064C9E6 /* AFPropertyListRequestOperation.h */,
|
||||
F8F4B16D143CD1410064C9E6 /* AFPropertyListRequestOperation.m */,
|
||||
F8FBFA96142AA237001409DB /* AFHTTPClient.h */,
|
||||
F8FBFA97142AA238001409DB /* AFHTTPClient.m */,
|
||||
F874B5D313E0AA6500B28E3E /* AFImageRequestOperation.h */,
|
||||
F874B5CB13E0AA6500B28E3E /* AFImageRequestOperation.m */,
|
||||
F8F4B16C143CD1410064C9E6 /* AFPropertyListRequestOperation.h */,
|
||||
F8F4B16D143CD1410064C9E6 /* AFPropertyListRequestOperation.m */,
|
||||
F874B5D213E0AA6500B28E3E /* AFImageCache.h */,
|
||||
F874B5CA13E0AA6500B28E3E /* AFImageCache.m */,
|
||||
F874B5D513E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.h */,
|
||||
|
||||
@ -22,6 +22,8 @@
|
||||
|
||||
#import "AFGowallaAPIClient.h"
|
||||
|
||||
#import "AFJSONRequestOperation.h"
|
||||
|
||||
// Replace this with your own API Key, available at http://api.gowalla.com/api/keys/
|
||||
NSString * const kAFGowallaClientID = @"e7ccb7d3d2414eb2af4663fc91eb2793";
|
||||
|
||||
@ -54,6 +56,8 @@ NSString * const kAFGowallaBaseURLString = @"https://api.gowalla.com/";
|
||||
// X-UDID HTTP Header
|
||||
[self setDefaultHeader:@"X-UDID" value:[[UIDevice currentDevice] uniqueIdentifier]];
|
||||
|
||||
[self registerHTTPOperationClass:[AFJSONRequestOperation class]];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
@ -43,6 +43,7 @@
|
||||
self.detailTextLabel.backgroundColor = self.backgroundColor;
|
||||
|
||||
self.imageView.backgroundColor = self.backgroundColor;
|
||||
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
|
||||
|
||||
self.selectionStyle = UITableViewCellSelectionStyleGray;
|
||||
|
||||
@ -73,4 +74,24 @@
|
||||
self.detailTextLabel.text = nil;
|
||||
}
|
||||
|
||||
#pragma mark - UIView
|
||||
|
||||
- (void)layoutSubviews {
|
||||
[super layoutSubviews];
|
||||
CGRect imageViewFrame = self.imageView.frame;
|
||||
CGRect textLabelFrame = self.textLabel.frame;
|
||||
CGRect detailTextLabelFrame = self.detailTextLabel.frame;
|
||||
|
||||
imageViewFrame.origin = CGPointMake(10.0f, 10.0f);
|
||||
imageViewFrame.size = CGSizeMake(50.0f, 50.0f);
|
||||
textLabelFrame.origin.x = imageViewFrame.size.width + 25.0f;
|
||||
detailTextLabelFrame.origin.x = textLabelFrame.origin.x;
|
||||
textLabelFrame.size.width = 240.0f;
|
||||
detailTextLabelFrame.size.width = textLabelFrame.size.width;
|
||||
|
||||
self.textLabel.frame = textLabelFrame;
|
||||
self.detailTextLabel.frame = detailTextLabelFrame;
|
||||
self.imageView.frame = imageViewFrame;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Loading…
Reference in New Issue
Block a user