From 2f2ee796ede1bed38975b3251493778d6660aab4 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Sat, 17 Dec 2011 23:49:51 -0600 Subject: [PATCH] Initial implementation of batched request operations --- AFNetworking/AFHTTPClient.h | 28 ++++++++++++++++++++++ AFNetworking/AFHTTPClient.m | 46 +++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/AFNetworking/AFHTTPClient.h b/AFNetworking/AFHTTPClient.h index a9905e7..e3fadf1 100644 --- a/AFNetworking/AFHTTPClient.h +++ b/AFNetworking/AFHTTPClient.h @@ -298,6 +298,34 @@ extern NSString * AFQueryStringFromParametersWithEncoding(NSDictionary *paramete */ - (void)cancelHTTPOperationsWithMethod:(NSString *)method andURL:(NSURL *)url; +///--------------------------------------- +/// @name Batching HTTP Request Operations +///--------------------------------------- + +/** + Creates and enqueues an `AFHTTPRequestOperation` to the HTTP client's operation queue for each specified request object into a batch. When each request operation finishes, the specified progress block is executed, until all of the request operations have finished, at which point the completion block also executes. + + @param requests The `NSURLRequest` objects used to create and enqueue operations. + @param progressBlock A block object to be executed upon the completion of each request operation in the batch. This block has no return value and takes two arguments: the number of operations that have already finished execution, and the total number of operations. + @param completionBlock A block object to be executed upon the completion of all of the request operations in the batch. This block has no return value and takes a single argument: the batched request operations. + + @discussion Operations are created by passing the specified `NSURLRequest` objects in `requests`, using `-HTTPRequestOperationWithRequest:success:failure:`, with `nil` for both the `success` and `failure` parameters. + */ +- (void)enqueueBatchOfHTTPRequestOperationsWithRequests:(NSArray *)requests + progressBlock:(void (^)(NSUInteger numberOfCompletedOperations, NSUInteger totalNumberOfOperations))progressBlock + completionBlock:(void (^)(NSArray *operations))completionBlock; + +/** + Enqueues the specified request operations into a batch. When each request operation finishes, the specified progress block is executed, until all of the request operations have finished, at which point the completion block also executes. + + @param operations The request operations used to be batched and enqueued. + @param progressBlock A block object to be executed upon the completion of each request operation in the batch. This block has no return value and takes two arguments: the number of operations that have already finished execution, and the total number of operations. + @param completionBlock A block object to be executed upon the completion of all of the request operations in the batch. This block has no return value and takes a single argument: the batched request operations. + */ +- (void)enqueueBatchOfHTTPRequestOperations:(NSArray *)operations + progressBlock:(void (^)(NSUInteger numberOfCompletedOperations, NSUInteger totalNumberOfOperations))progressBlock + completionBlock:(void (^)(NSArray *operations))completionBlock; + ///--------------------------- /// @name Making HTTP Requests ///--------------------------- diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index dbb66b5..5cdfa16 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -49,6 +49,8 @@ static NSString * const kAFMultipartFormBoundary = @"Boundary+0xAbCdEfGbOuNdArY" #pragma mark - +typedef void (^_AFCompletionBlock)(void); + static NSUInteger const kAFHTTPClientDefaultMaxConcurrentOperationCount = 4; static NSString * AFBase64EncodedStringFromString(NSString *string) { @@ -335,6 +337,50 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) { } } +- (void)enqueueBatchOfHTTPRequestOperationsWithRequests:(NSArray *)requests + progressBlock:(void (^)(NSUInteger numberOfCompletedOperations, NSUInteger totalNumberOfOperations))progressBlock + completionBlock:(void (^)(NSArray *operations))completionBlock +{ + NSMutableArray *mutableOperations = [NSMutableArray array]; + for (NSURLRequest *request in requests) { + AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:nil failure:nil]; + [mutableOperations addObject:operation]; + } + + [self enqueueBatchOfHTTPRequestOperations:mutableOperations progressBlock:progressBlock completionBlock:completionBlock]; +} + +- (void)enqueueBatchOfHTTPRequestOperations:(NSArray *)operations + progressBlock:(void (^)(NSUInteger numberOfCompletedOperations, NSUInteger totalNumberOfOperations))progressBlock + completionBlock:(void (^)(NSArray *operations))completionBlock +{ + NSBlockOperation *batchedOperation = [NSBlockOperation blockOperationWithBlock:^{ + if (completionBlock) { + completionBlock(operations); + } + }]; + + [self.operationQueue addOperation:batchedOperation]; + + NSPredicate *finishedOperationPredicate = [NSPredicate predicateWithFormat:@"isFinished == YES"]; + + for (AFHTTPRequestOperation *operation in operations) { + _AFCompletionBlock originalCompletionBlock = [[operation.completionBlock copy] autorelease]; + operation.completionBlock = ^{ + if (progressBlock) { + progressBlock([[batchedOperation.dependencies filteredArrayUsingPredicate:finishedOperationPredicate] count], [batchedOperation.dependencies count]); + } + + if (originalCompletionBlock) { + originalCompletionBlock(); + } + }; + + [batchedOperation addDependency:operation]; + [self enqueueHTTPRequestOperation:operation]; + } +} + #pragma mark - - (void)getPath:(NSString *)path