diff --git a/AFNetworking/AFHTTPClient.h b/AFNetworking/AFHTTPClient.h index 72dce8e..6797d4f 100644 --- a/AFNetworking/AFHTTPClient.h +++ b/AFNetworking/AFHTTPClient.h @@ -316,6 +316,34 @@ extern NSString * AFQueryStringFromParametersWithEncoding(NSDictionary *paramete */ - (void)cancelAllHTTPOperationsWithMethod:(NSString *)method path:(NSString *)path; +///--------------------------------------- +/// @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 a918744..6ddebdc 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -60,6 +60,7 @@ typedef id AFNetworkReachabilityRef; #endif typedef void (^AFNetworkReachabilityStatusBlock)(BOOL isNetworkReachable); +typedef void (^AFCompletionBlock)(void); static NSUInteger const kAFHTTPClientDefaultMaxConcurrentOperationCount = 4; @@ -391,6 +392,50 @@ static void AFReachabilityCallback(SCNetworkReachabilityRef __unused target, SCN } } +- (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