diff --git a/AFNetworking/AFHTTPClient.h b/AFNetworking/AFHTTPClient.h index 728d4ce156..85427d0dce 100644 --- a/AFNetworking/AFHTTPClient.h +++ b/AFNetworking/AFHTTPClient.h @@ -125,20 +125,20 @@ typedef enum { ///---------------------------------- /** - Attempts to register a class conforming to the `AFHTTPClientOperation` protocol, adding it to a chain to automatically generate request operations from a URL request. + Attempts to register a subclass of `AFHTTPRequestOperation`, adding it to a chain to automatically generate request operations from a URL request. - @param The class conforming to the `AFHTTPClientOperation` protocol to register + @param The subclass of `AFHTTPRequestOperation` to register - @return `YES` if the registration is successful, `NO` otherwise. The only failure condition is if `operationClass` does not conform to the `AFHTTPCLientOperation` protocol. + @return `YES` if the registration is successful, `NO` otherwise. The only failure condition is if `operationClass` does is not a subclass of `AFHTTPRequestOperation`. - @discussion When `enqueueHTTPRequestOperationWithRequest:success:failure` is invoked, each registered class is consulted in turn to see if it can handle the specific request. The first class to return `YES` when sent a `canProcessRequest:` message is used to generate an operation using `HTTPRequestOperationWithRequest:success:failure:`. There is no guarantee that all registered classes will be consulted. Classes are consulted in the reverse order of their registration. Attempting to register an already-registered class will move it to the top of the chain. + @discussion When `enqueueHTTPRequestOperationWithRequest:success:failure` is invoked, each registered class is consulted in turn to see if it can handle the specific request. The first class to return `YES` when sent a `canProcessRequest:` message is used to create an operation using `initWithURLRequest:` and do `setCompletionBlockWithSuccess:failure:`. There is no guarantee that all registered classes will be consulted. Classes are consulted in the reverse order of their registration. Attempting to register an already-registered class will move it to the top of the list. @see `AFHTTPClientOperation` */ - (BOOL)registerHTTPOperationClass:(Class)operationClass; /** - Unregisteres the specified class conforming to the `AFHTTPClientOperation` protocol. + Unregisters the specified subclass of `AFHTTPRequestOperation`. @param The class conforming to the `AFHTTPClientOperation` protocol to unregister @@ -244,8 +244,8 @@ typedef enum { @see `AFHTTPClientOperation` */ - (void)enqueueHTTPRequestOperationWithRequest:(NSURLRequest *)request - success:(void (^)(id object))success - failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure; + success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; /** Enqueues an `AFHTTPRequestOperation` to the HTTP client's operation queue. @@ -281,8 +281,8 @@ typedef enum { */ - (void)getPath:(NSString *)path parameters:(NSDictionary *)parameters - success:(void (^)(id object))success - failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure; + success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; /** Creates an `AFHTTPRequestOperation` with a `POST` request, and enqueues it to the HTTP client's operation queue. @@ -296,8 +296,8 @@ typedef enum { */ - (void)postPath:(NSString *)path parameters:(NSDictionary *)parameters - success:(void (^)(id object))success - failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure; + success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; /** Creates an `AFHTTPRequestOperation` with a `PUT` request, and enqueues it to the HTTP client's operation queue. @@ -311,8 +311,8 @@ typedef enum { */ - (void)putPath:(NSString *)path parameters:(NSDictionary *)parameters - success:(void (^)(id object))success - failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure; + success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; /** Creates an `AFHTTPRequestOperation` with a `DELETE` request, and enqueues it to the HTTP client's operation queue. @@ -326,36 +326,8 @@ typedef enum { */ - (void)deletePath:(NSString *)path parameters:(NSDictionary *)parameters - success:(void (^)(id object))success - failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure; -@end - -#pragma mark - - -/** - The `AFHTTPClientOperation` protocol defines the methods used for the automatic content parsing functionality of `AFHTTPClient`. - - @see `AFHTTPClient -registerHTTPOperationClass:` - */ -@protocol AFHTTPClientOperation - -/** - A Boolean value determining whether or not the class can process the specified request. For example, `AFJSONRequestOperation` may check to make sure the content type was `application/json` or the URL path extension was `.json`. - - @param urlRequest The request that is determined to be supported or not supported for this class. - */ -+ (BOOL)canProcessRequest:(NSURLRequest *)urlRequest; - -/** - Constructs and initializes an operation with success and failure callbacks. - - @param urlRequest The request used by the operation connection. - @param success A block object to be executed when the operation finishes successfully. The block has no return value and takes a single argument, the response object from the request. - @param failure A block object to be executed when the operation finishes unsuccessfully. The block has no return value and takes two arguments: the response received from the server, and the error describing the network or parsing error that occurred. - */ -+ (id)HTTPRequestOperationWithRequest:(NSURLRequest *)urlRequest - success:(void (^)(id object))success - failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure; + success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; @end #pragma mark - diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index 0c988b1af9..c6e69cbddd 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -208,7 +208,7 @@ - (void)dealloc { #pragma mark - - (BOOL)registerHTTPOperationClass:(Class)operationClass { - if (![operationClass conformsToProtocol:@protocol(AFHTTPClientOperation)]) { + if (![operationClass isSubclassOfClass:[AFHTTPRequestOperation class]]) { return NO; } @@ -325,8 +325,8 @@ - (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method } - (void)enqueueHTTPRequestOperationWithRequest:(NSURLRequest *)urlRequest - success:(void (^)(id object))success - failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure + success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure { AFHTTPRequestOperation *operation = nil; NSString *className = nil; @@ -334,13 +334,15 @@ - (void)enqueueHTTPRequestOperationWithRequest:(NSURLRequest *)urlRequest while (!operation && (className = [enumerator nextObject])) { Class class = NSClassFromString(className); if (class && [class canProcessRequest:urlRequest]) { - operation = [class HTTPRequestOperationWithRequest:urlRequest success:success failure:failure]; + operation = [[(AFHTTPRequestOperation *)[class alloc] initWithRequest:urlRequest] autorelease]; } } if (!operation) { - operation = [AFHTTPRequestOperation HTTPRequestOperationWithRequest:urlRequest success:success failure:failure]; + operation = [[AFHTTPRequestOperation alloc] initWithRequest:urlRequest]; } + + [operation setCompletionBlockWithSuccess:success failure:failure]; [self enqueueHTTPRequestOperation:operation]; } @@ -361,8 +363,8 @@ - (void)cancelHTTPOperationsWithMethod:(NSString *)method andURL:(NSURL *)url { - (void)getPath:(NSString *)path parameters:(NSDictionary *)parameters - success:(void (^)(id object))success - failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure + success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure { NSURLRequest *request = [self requestWithMethod:@"GET" path:path parameters:parameters]; [self enqueueHTTPRequestOperationWithRequest:request success:success failure:failure]; @@ -370,8 +372,8 @@ - (void)getPath:(NSString *)path - (void)postPath:(NSString *)path parameters:(NSDictionary *)parameters - success:(void (^)(id object))success - failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure + success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure { NSURLRequest *request = [self requestWithMethod:@"POST" path:path parameters:parameters]; [self enqueueHTTPRequestOperationWithRequest:request success:success failure:failure]; @@ -379,8 +381,8 @@ - (void)postPath:(NSString *)path - (void)putPath:(NSString *)path parameters:(NSDictionary *)parameters - success:(void (^)(id object))success - failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure + success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure { NSURLRequest *request = [self requestWithMethod:@"PUT" path:path parameters:parameters]; [self enqueueHTTPRequestOperationWithRequest:request success:success failure:failure]; @@ -388,8 +390,8 @@ - (void)putPath:(NSString *)path - (void)deletePath:(NSString *)path parameters:(NSDictionary *)parameters - success:(void (^)(id object))success - failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure + success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure { NSURLRequest *request = [self requestWithMethod:@"DELETE" path:path parameters:parameters]; [self enqueueHTTPRequestOperationWithRequest:request success:success failure:failure]; diff --git a/AFNetworking/AFHTTPRequestOperation.h b/AFNetworking/AFHTTPRequestOperation.h index d93ea67b61..8ca50f647c 100644 --- a/AFNetworking/AFHTTPRequestOperation.h +++ b/AFNetworking/AFHTTPRequestOperation.h @@ -22,12 +22,11 @@ #import #import "AFURLConnectionOperation.h" -#import "AFHTTPClient.h" /** `AFHTTPRequestOperation` is a subclass of `AFURLConnectionOperation` for requests using the HTTP or HTTPS protocols. It encapsulates the concept of acceptable status codes and content types, which determine the success or failure of a request. */ -@interface AFHTTPRequestOperation : AFURLConnectionOperation { +@interface AFHTTPRequestOperation : AFURLConnectionOperation { @private NSIndexSet *_acceptableStatusCodes; NSSet *_acceptableContentTypes; @@ -72,4 +71,21 @@ */ @property (readonly) BOOL hasAcceptableContentType; +/** + A Boolean value determining whether or not the class can process the specified request. For example, `AFJSONRequestOperation` may check to make sure the content type was `application/json` or the URL path extension was `.json`. + + @param urlRequest The request that is determined to be supported or not supported for this class. + */ ++ (BOOL)canProcessRequest:(NSURLRequest *)urlRequest; + +///----------------------------------------------------------- +/// @name Setting Completion Block Success / Failure Callbacks +///----------------------------------------------------------- + +/** + + */ +- (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; + @end diff --git a/AFNetworking/AFHTTPRequestOperation.m b/AFNetworking/AFHTTPRequestOperation.m index ceaa39baca..c754af74af 100644 --- a/AFNetworking/AFHTTPRequestOperation.m +++ b/AFNetworking/AFHTTPRequestOperation.m @@ -23,14 +23,14 @@ #import "AFHTTPRequestOperation.h" @interface AFHTTPRequestOperation () -@property (readwrite, nonatomic, retain) NSError *error; +@property (readwrite, nonatomic, retain) NSError *HTTPError; @property (readonly, nonatomic, assign) BOOL hasContent; @end @implementation AFHTTPRequestOperation @synthesize acceptableStatusCodes = _acceptableStatusCodes; @synthesize acceptableContentTypes = _acceptableContentTypes; -@synthesize error = _HTTPError; +@synthesize HTTPError = _HTTPError; - (id)initWithRequest:(NSURLRequest *)request { self = [super initWithRequest:request]; @@ -55,23 +55,27 @@ - (NSHTTPURLResponse *)response { } - (NSError *)error { - if (self.response) { + if (self.response && !self.HTTPError) { if (![self hasAcceptableStatusCode]) { NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; [userInfo setValue:[NSString stringWithFormat:NSLocalizedString(@"Expected status code %@, got %d", nil), self.acceptableStatusCodes, [self.response statusCode]] forKey:NSLocalizedDescriptionKey]; [userInfo setValue:[self.request URL] forKey:NSURLErrorFailingURLErrorKey]; - self.error = [[[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadServerResponse userInfo:userInfo] autorelease]; + self.HTTPError = [[[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadServerResponse userInfo:userInfo] autorelease]; } else if ([self hasContent] && ![self hasAcceptableContentType]) { // Don't invalidate content type if there is no content NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; [userInfo setValue:[NSString stringWithFormat:NSLocalizedString(@"Expected content type %@, got %@", nil), self.acceptableContentTypes, [self.response MIMEType]] forKey:NSLocalizedDescriptionKey]; [userInfo setValue:[self.request URL] forKey:NSURLErrorFailingURLErrorKey]; - self.error = [[[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:userInfo] autorelease]; + self.HTTPError = [[[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:userInfo] autorelease]; } } - return _HTTPError; + if (_HTTPError) { + return _HTTPError; + } else { + return [super error]; + } } - (BOOL)hasContent { @@ -86,38 +90,34 @@ - (BOOL)hasAcceptableContentType { return !self.acceptableContentTypes || [self.acceptableContentTypes containsObject:[self.response MIMEType]]; } -#pragma mark - AFHTTPClientOperation - -+ (BOOL)canProcessRequest:(NSURLRequest *)request { - return NO; -} - -+ (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)urlRequest - success:(void (^)(id object))success - failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure +- (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure { - AFHTTPRequestOperation *operation = [[[self alloc] initWithRequest:urlRequest] autorelease]; - operation.completionBlock = ^ { - if ([operation isCancelled]) { + self.completionBlock = ^ { + if ([self isCancelled]) { return; } - if (operation.error) { + if (self.error) { if (failure) { dispatch_async(dispatch_get_main_queue(), ^(void) { - failure(operation.response, operation.error); + failure(self, self.error); }); } } else { if (success) { - dispatch_async(dispatch_get_main_queue(), ^(void) { - success(operation.responseData); + dispatch_async(dispatch_get_main_queue(), ^{ + success(self, self.responseData); }); } } }; - - return operation; -} +} + +#pragma mark - AFHTTPClientOperation + ++ (BOOL)canProcessRequest:(NSURLRequest *)request { + return YES; +} @end diff --git a/AFNetworking/AFJSONRequestOperation.h b/AFNetworking/AFJSONRequestOperation.h index b489343147..53b8ec2d2a 100644 --- a/AFNetworking/AFJSONRequestOperation.h +++ b/AFNetworking/AFJSONRequestOperation.h @@ -62,6 +62,6 @@ @return A new JSON request operation */ + (AFJSONRequestOperation *)JSONRequestOperationWithRequest:(NSURLRequest *)urlRequest - success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON))success - failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure; + success:(void (^)(NSURLRequest *request, NSURLResponse *response, id JSON))success + failure:(void (^)(NSURLRequest *request, NSURLResponse *response, NSError *error, id JSON))failure; @end diff --git a/AFNetworking/AFJSONRequestOperation.m b/AFNetworking/AFJSONRequestOperation.m index 16d1465cb8..ec570fff31 100644 --- a/AFNetworking/AFJSONRequestOperation.m +++ b/AFNetworking/AFJSONRequestOperation.m @@ -48,41 +48,21 @@ @implementation AFJSONRequestOperation @synthesize JSONError = _JSONError; + (AFJSONRequestOperation *)JSONRequestOperationWithRequest:(NSURLRequest *)urlRequest - success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON))success - failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure + success:(void (^)(NSURLRequest *request, NSURLResponse *response, id JSON))success + failure:(void (^)(NSURLRequest *request, NSURLResponse *response, NSError *error, id JSON))failure { - AFJSONRequestOperation *operation = [[[self alloc] initWithRequest:urlRequest] autorelease]; - operation.completionBlock = ^ { - if ([operation isCancelled]) { - return; + AFJSONRequestOperation *requestOperation = [[[self alloc] initWithRequest:urlRequest] autorelease]; + [requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { + if (success) { + success(operation.request, operation.response, responseObject); } - - if (operation.error) { - if (failure) { - dispatch_async(dispatch_get_main_queue(), ^(void) { - failure(operation.request, operation.response, operation.error); - }); - } - } else { - dispatch_async(json_request_operation_processing_queue(), ^(void) { - id JSON = operation.responseJSON; - - dispatch_async(dispatch_get_main_queue(), ^(void) { - if (operation.error) { - if (failure) { - failure(operation.request, operation.response, operation.error); - } - } else { - if (success) { - success(operation.request, operation.response, JSON); - } - } - }); - }); + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + if (failure) { + failure(operation.request, operation.response, error, [(AFJSONRequestOperation *)operation responseJSON]); } - }; + }]; - return operation; + return requestOperation; } + (NSSet *)defaultAcceptableContentTypes { @@ -93,6 +73,10 @@ + (NSSet *)defaultAcceptablePathExtensions { return [NSSet setWithObjects:@"json", nil]; } ++ (BOOL)canProcessRequest:(NSURLRequest *)request { + return [[self defaultAcceptableContentTypes] containsObject:[request valueForHTTPHeaderField:@"Accept"]] || [[self defaultAcceptablePathExtensions] containsObject:[[request URL] pathExtension]]; +} + - (id)initWithRequest:(NSURLRequest *)urlRequest { self = [super initWithRequest:urlRequest]; if (!self) { @@ -143,21 +127,38 @@ - (NSError *)error { } } -#pragma mark - AFHTTPClientOperation - -+ (BOOL)canProcessRequest:(NSURLRequest *)request { - return [[self defaultAcceptableContentTypes] containsObject:[request valueForHTTPHeaderField:@"Accept"]] || [[self defaultAcceptablePathExtensions] containsObject:[[request URL] pathExtension]]; -} - -+ (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)urlRequest - success:(void (^)(id object))success - failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure +- (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(void (^)(AFHTTPRequestOperation *operation, 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); - }]; + self.completionBlock = ^ { + if ([self isCancelled]) { + return; + } + + if (self.error) { + if (failure) { + dispatch_async(dispatch_get_main_queue(), ^(void) { + failure(self, self.error); + }); + } + } else { + dispatch_async(json_request_operation_processing_queue(), ^(void) { + id JSON = self.responseJSON; + + dispatch_async(dispatch_get_main_queue(), ^(void) { + if (self.JSONError) { + if (failure) { + failure(self, self.JSONError); + } + } else { + if (success) { + success(self, JSON); + } + } + }); + }); + } + }; } @end diff --git a/AFNetworking/AFPropertyListRequestOperation.h b/AFNetworking/AFPropertyListRequestOperation.h index bc02738278..f0016563ed 100644 --- a/AFNetworking/AFPropertyListRequestOperation.h +++ b/AFNetworking/AFPropertyListRequestOperation.h @@ -69,6 +69,6 @@ */ + (AFPropertyListRequestOperation *)propertyListRequestOperationWithRequest:(NSURLRequest *)request success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, id propertyList))success - failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure; + failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id propertyList))failure; @end diff --git a/AFNetworking/AFPropertyListRequestOperation.m b/AFNetworking/AFPropertyListRequestOperation.m index 01a81b14c1..7d846204ef 100644 --- a/AFNetworking/AFPropertyListRequestOperation.m +++ b/AFNetworking/AFPropertyListRequestOperation.m @@ -34,7 +34,7 @@ static dispatch_queue_t property_list_request_operation_processing_queue() { @interface AFPropertyListRequestOperation () @property (readwrite, nonatomic, retain) id responsePropertyList; @property (readwrite, nonatomic, assign) NSPropertyListFormat propertyListFormat; -@property (readwrite, nonatomic, retain) NSError *error; +@property (readwrite, nonatomic, retain) NSError *propertyListError; + (NSSet *)defaultAcceptableContentTypes; + (NSSet *)defaultAcceptablePathExtensions; @@ -44,44 +44,24 @@ @implementation AFPropertyListRequestOperation @synthesize responsePropertyList = _responsePropertyList; @synthesize propertyListReadOptions = _propertyListReadOptions; @synthesize propertyListFormat = _propertyListFormat; -@synthesize error = _propertyListError; +@synthesize propertyListError = _propertyListError; + (AFPropertyListRequestOperation *)propertyListRequestOperationWithRequest:(NSURLRequest *)request success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, id propertyList))success - failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure + failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id propertyList))failure { - AFPropertyListRequestOperation *operation = [[[self alloc] initWithRequest:request] autorelease]; - operation.completionBlock = ^ { - if ([operation isCancelled]) { - return; + AFPropertyListRequestOperation *requestOperation = [[[self alloc] initWithRequest:request] autorelease]; + [requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { + if (success) { + success(operation.request, operation.response, responseObject); } - - if (operation.error) { - if (failure) { - dispatch_async(dispatch_get_main_queue(), ^(void) { - failure(operation.request, operation.response, operation.error); - }); - } - } else { - dispatch_async(property_list_request_operation_processing_queue(), ^(void) { - id propertyList = operation.responsePropertyList; - - dispatch_async(dispatch_get_main_queue(), ^(void) { - if (operation.error) { - if (failure) { - failure(operation.request, operation.response, operation.error); - } - } else { - if (success) { - success(operation.request, operation.response, propertyList); - } - } - }); - }); + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + if (failure) { + failure(operation.request, operation.response, error, [(AFPropertyListRequestOperation *)operation responsePropertyList]); } - }; + }]; - return operation; + return requestOperation; } + (NSSet *)defaultAcceptableContentTypes { @@ -117,27 +97,56 @@ - (id)responsePropertyList { NSError *error = nil; self.responsePropertyList = [NSPropertyListSerialization propertyListWithData:self.responseData options:self.propertyListReadOptions format:&format error:&error]; self.propertyListFormat = format; - self.error = error; + self.propertyListError = error; } return _responsePropertyList; } -#pragma mark - AFHTTPClientOperation +- (NSError *)error { + if (_propertyListError) { + return _propertyListError; + } else { + return [super error]; + } +} + (BOOL)canProcessRequest:(NSURLRequest *)request { return [[self defaultAcceptableContentTypes] containsObject:[request valueForHTTPHeaderField:@"Accept"]] || [[self defaultAcceptablePathExtensions] containsObject:[[request URL] pathExtension]]; } -+ (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)urlRequest - success:(void (^)(id object))success - failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure +- (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(void (^)(AFHTTPRequestOperation *operation, 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); - }]; + self.completionBlock = ^ { + if ([self isCancelled]) { + return; + } + + if (self.error) { + if (failure) { + dispatch_async(dispatch_get_main_queue(), ^(void) { + failure(self, self.error); + }); + } + } else { + dispatch_async(property_list_request_operation_processing_queue(), ^(void) { + id propertyList = self.responsePropertyList; + + dispatch_async(dispatch_get_main_queue(), ^(void) { + if (self.propertyListError) { + if (failure) { + failure(self, self.propertyListError); + } + } else { + if (success) { + success(self, propertyList); + } + } + }); + }); + } + }; } @end diff --git a/AFNetworking/AFXMLRequestOperation.h b/AFNetworking/AFXMLRequestOperation.h index 441a841396..702fe2d2e4 100644 --- a/AFNetworking/AFXMLRequestOperation.h +++ b/AFNetworking/AFXMLRequestOperation.h @@ -71,7 +71,7 @@ */ + (AFXMLRequestOperation *)XMLParserRequestOperationWithRequest:(NSURLRequest *)urlRequest success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSXMLParser *XMLParser))success - failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure; + failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, NSXMLParser *XMLParse))failure; #if __MAC_OS_X_VERSION_MIN_REQUIRED @@ -86,7 +86,7 @@ */ + (AFXMLRequestOperation *)XMLDocumentRequestOperationWithRequest:(NSURLRequest *)urlRequest success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSXMLDocument *document))success - failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure; + failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, NSXMLDocument *document))failure; #endif @end diff --git a/AFNetworking/AFXMLRequestOperation.m b/AFNetworking/AFXMLRequestOperation.m index 26ff4b1c03..9a3407ed09 100644 --- a/AFNetworking/AFXMLRequestOperation.m +++ b/AFNetworking/AFXMLRequestOperation.m @@ -53,37 +53,26 @@ @implementation AFXMLRequestOperation + (AFXMLRequestOperation *)XMLParserRequestOperationWithRequest:(NSURLRequest *)urlRequest success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSXMLParser *XMLParser))success - failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure + failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, NSXMLParser *XMLParser))failure { - AFXMLRequestOperation *operation = [[[self alloc] initWithRequest:urlRequest] autorelease]; - operation.completionBlock = ^ { - if ([operation isCancelled]) { - return; + AFXMLRequestOperation *requestOperation = [[[self alloc] initWithRequest:urlRequest] autorelease]; + [requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { + if (success) { + success(operation.request, operation.response, responseObject); } - - if (operation.error) { - if (failure) { - dispatch_async(dispatch_get_main_queue(), ^(void) { - failure(operation.request, operation.response, operation.error); - }); - } - } else { - NSXMLParser *XMLParser = operation.responseXMLParser; - if (success) { - dispatch_async(dispatch_get_main_queue(), ^(void) { - success(operation.request, operation.response, XMLParser); - }); - } + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + if (failure) { + failure(operation.request, operation.response, error, [(AFXMLRequestOperation *)operation responseXMLParser]); } - }; + }]; - return operation; + return requestOperation; } #if __MAC_OS_X_VERSION_MIN_REQUIRED + (AFXMLRequestOperation *)XMLDocumentRequestOperationWithRequest:(NSURLRequest *)urlRequest success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSXMLDocument *document))success - failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure + failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, NSXMLDocument *document))failure { AFXMLRequestOperation *operation = [[[self alloc] initWithRequest:urlRequest] autorelease]; operation.completionBlock = ^ { @@ -94,7 +83,7 @@ + (AFXMLRequestOperation *)XMLDocumentRequestOperationWithRequest:(NSURLRequest if (operation.error) { if (failure) { dispatch_async(dispatch_get_main_queue(), ^(void) { - failure(operation.request, operation.response, operation.error); + failure(operation.request, operation.response, operation.error, [(AFXMLRequestOperation *)operation responseXMLDocument]); }); } } else { @@ -165,6 +154,14 @@ - (NSXMLDocument *)responseXMLDocument { } #endif +- (NSError *)error { + if (_XMLError) { + return _XMLError; + } else { + return [super error]; + } +} + #pragma mark - NSOperation - (void)cancel { @@ -173,29 +170,36 @@ - (void)cancel { self.responseXMLParser.delegate = nil; } -#pragma mark - AFHTTPClientOperation - + (BOOL)canProcessRequest:(NSURLRequest *)request { return [[self defaultAcceptableContentTypes] containsObject:[request valueForHTTPHeaderField:@"Accept"]] || [[self defaultAcceptablePathExtensions] containsObject:[[request URL] pathExtension]]; } -+ (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)urlRequest - success:(void (^)(id object))success - failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure +- (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure { + self.completionBlock = ^ { + if ([self isCancelled]) { + return; + } + + if (self.error) { + if (failure) { + dispatch_async(dispatch_get_main_queue(), ^(void) { + failure(self, self.error); + }); + } + } else { #if __MAC_OS_X_VERSION_MIN_REQUIRED - return [self XMLDocumentRequestOperationWithRequest:urlRequest success:^(NSURLRequest __unused *request, NSHTTPURLResponse __unused *response, NSXMLDocument *XMLDocument) { - success(XMLDocument); - } failure:^(NSURLRequest __unused *request, NSHTTPURLResponse *response, NSError *error) { - failure(response, error); - }]; + if (success) { + success(self, self.responseXMLDocument); + } #else - return [self XMLParserRequestOperationWithRequest:urlRequest success:^(NSURLRequest __unused *request, NSHTTPURLResponse __unused *response, NSXMLParser *XMLParser) { - success(XMLParser); - } failure:^(NSURLRequest __unused *request, NSHTTPURLResponse *response, NSError *error) { - failure(response, error); - }]; + if (success) { + success(self, self.responseXMLParser); + } #endif + } + }; } @end diff --git a/Mac Example/Classes/Models/Spot.m b/Mac Example/Classes/Models/Spot.m index ae7c577fe3..9f554f5563 100644 --- a/Mac Example/Classes/Models/Spot.m +++ b/Mac Example/Classes/Models/Spot.m @@ -56,17 +56,19 @@ + (void)spotsWithURLString:(NSString *)urlString near:(CLLocation *)location par [mutableParameters setValue:[NSString stringWithFormat:@"%1.7f", location.coordinate.longitude] forKey:@"lng"]; } - [[AFGowallaAPIClient sharedClient] getPath:urlString parameters:mutableParameters success:^(id object) { + [[AFGowallaAPIClient sharedClient] getPath:urlString parameters:mutableParameters success:^(__unused AFHTTPRequestOperation *operation, id JSON) { NSMutableArray *mutableRecords = [NSMutableArray array]; - for (NSDictionary *attributes in [object valueForKeyPath:@"spots"]) { - Spot *spot = [[Spot alloc] initWithAttributes:attributes]; - [mutableRecords addObject:spot]; + for (NSDictionary *attributes in [JSON valueForKeyPath:@"spots"]) { + @autoreleasepool { + Spot *spot = [[Spot alloc] initWithAttributes:attributes]; + [mutableRecords addObject:spot]; + } } if (block) { block([NSArray arrayWithArray:mutableRecords]); } - } failure:^(NSHTTPURLResponse *response, NSError *error) { + } failure:^(__unused AFHTTPRequestOperation *operation, NSError *error) { if (block) { block([NSArray array]); } diff --git a/iOS Example/Classes/Models/Spot.m b/iOS Example/Classes/Models/Spot.m index bd7272a67e..6e2edde6ab 100644 --- a/iOS Example/Classes/Models/Spot.m +++ b/iOS Example/Classes/Models/Spot.m @@ -64,9 +64,9 @@ + (void)spotsWithURLString:(NSString *)urlString near:(CLLocation *)location par [mutableParameters setValue:[NSString stringWithFormat:@"%1.7f", location.coordinate.longitude] forKey:@"lng"]; } - [[AFGowallaAPIClient sharedClient] getPath:urlString parameters:mutableParameters success:^(id object) { + [[AFGowallaAPIClient sharedClient] getPath:urlString parameters:mutableParameters success:^(__unused AFHTTPRequestOperation *operation, id JSON) { NSMutableArray *mutableRecords = [NSMutableArray array]; - for (NSDictionary *attributes in [object valueForKeyPath:@"spots"]) { + for (NSDictionary *attributes in [JSON valueForKeyPath:@"spots"]) { Spot *spot = [[[Spot alloc] initWithAttributes:attributes] autorelease]; [mutableRecords addObject:spot]; } @@ -74,7 +74,7 @@ + (void)spotsWithURLString:(NSString *)urlString near:(CLLocation *)location par if (block) { block([NSArray arrayWithArray:mutableRecords]); } - } failure:^(NSHTTPURLResponse *response, NSError *error) { + } failure:^(__unused AFHTTPRequestOperation *operation, NSError *error) { if (block) { block([NSArray array]); }