AFNetworking cancelAllOperations可防止批量完成块被触发

时间:2013-07-22 00:10:37

标签: objective-c afnetworking nsoperation nsoperationqueue

我正在使用enqueueBatchOfHTTPRequestOperations提交一批请求。如果任何请求失败,我想立即取消任何其他仍在进行的请求。为此,我将单个操作的故障回调设置为[client.operationQueue cancelAllOperations];

这似乎取消了所有剩余的操作,但它也阻止了批处理的整个completionBlock执行......这是我试图用这个行为测试的代码(其中一个请求总是设置为失败的服务器)。

AFHTTPClient *client = [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:@"http://arahlf.com"]];

NSMutableArray *requests = [[NSMutableArray alloc] init];

for (int i = 0; i < 10; i++) {
    NSURLRequest *request = [client requestWithMethod:@"GET" path:@"echo.php" parameters:@{ @"sleep": @(i) }];
    AFHTTPRequestOperation *operation = [client HTTPRequestOperationWithRequest:request success:nil failure:nil];
    [operation setCompletionBlockWithSuccess:nil failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Request failed, cancelling all operations.");
        [client.operationQueue cancelAllOperations];
    }];

    [requests addObject:operation];
}

[client enqueueBatchOfHTTPRequestOperations:requests progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) {
    NSLog(@"Progress: %i/%i", numberOfFinishedOperations, totalNumberOfOperations);

} completionBlock:^(NSArray *operations) {
    NSLog(@"All done!");
}];

对我来说,从未执行completionBlock。此外,由于一个失败的请求会取消剩余的请求(也会触发失败块),cancelAllOperations实际上会多次执行。

有没有更好的方法来实现这种效果?

1 个答案:

答案 0 :(得分:5)

当您执行operationQueue cancelAllOperations时,除了所有其他操作之外,您实际上取消了批量完成时触发的依赖操作。

也就是说,在您的示例中,取消了11个操作:10个网络操作+从属批量完成操作。

setCompletionblock:...中的以下更改允许批量完成按预期方式触发:

[[client.operationQueue.operations filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
  return [evaluatedObject isKindOfClass:[AFHTTPRequestOperation class]];
}]] makeObjectsPerformSelector:@selector(cancel)];