NSURLConnection sendAsynchronousRequest:queue:completionHandler:连续发出多个请求?

Nic*_*ard 53 objective-c nsurlconnection ios ios5

我一直在使用NSURLConnection's sendAsynchronousRequest:queue:completionHandler:很棒的方法.但是,我现在需要连续发出多个请求.

如何在使用这种伟大的异步方法的同时做到这一点?

yuj*_*uji 108

根据您想要的行为,您可以通过多种方式执行此操作.

您可以一次发送一堆异步请求,跟踪已完成的请求数,并在完成所有操作后执行一些操作:

NSInteger outstandingRequests = [requestsArray count];
for (NSURLRequest *request in requestsArray) {
    [NSURLConnection sendAsynchronousRequest:request 
                                       queue:[NSOperationQueue mainQueue]
                           completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
        [self doSomethingWithData:data];
        outstandingRequests--;
        if (outstandingRequests == 0) {
            [self doSomethingElse];
        }
    }];
}
Run Code Online (Sandbox Code Playgroud)

你可以把块连在一起:

NSMutableArray *dataArray = [NSMutableArray array];    
__block (^handler)(NSURLResponse *response, NSData *data, NSError *error);

NSInteger currentRequestIndex = 0;
handler = ^{
    [dataArray addObject:data];
    currentRequestIndex++;
    if (currentRequestIndex < [requestsArray count]) {
        [NSURLConnection sendAsynchronousRequest:[requestsArray objectAtIndex:currentRequestIndex] 
                                   queue:[NSOperationQueue mainQueue]
                       completionHandler:handler];
    } else {
        [self doSomethingElse];
    }
};
[NSURLConnection sendAsynchronousRequest:[requestsArray objectAtIndex:0] 
                                   queue:[NSOperationQueue mainQueue]
                       completionHandler:handler];
Run Code Online (Sandbox Code Playgroud)

或者您可以在ansynchronous块中同步执行所有请求:

dispatch_queue_t callerQueue = dispatch_get_current_queue();
dispatch_queue_t downloadQueue = dispatch_queue_create("Lots of requests", NULL);
    dispatch_async(downloadQueue, ^{
        for (NSRURLRequest *request in requestsArray) {
            [dataArray addObject:[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]];
        }
        dispatch_async(callerQueue, ^{
            [self doSomethingWithDataArray:dataArray];
        });
    });
});
Run Code Online (Sandbox Code Playgroud)

PS如果你使用其中任何一个,你应该添加一些错误检查.

  • `dispatch_async`这里**正在使用**后台线程.但是从后台请求调用同步请求没有任何问题.实际上,[文档](https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html)明确不鼓励您在GUI应用程序的主要线程,因为它会阻止UI. (4认同)
  • `sendAsynchronousRequest:queue:completionHandler:`异步发送请求(即,在后台,不阻塞主线程).当响应返回时,处理程序块将被分派到指定队列中指定的队列. (3认同)
  • @ yuji,在阅读了sendAsynchronousRequest文档后,看看上面的第一个选项,我仍然不清楚该方法中的队列定义.这是用于下载的队列,因此不应该是主队列,例如你上面的队列,或者异步下载是否会在某个其他队列上发生,除了主队列和方法中的队列应该是后期下载任务的主要队列.谢谢九巴 (2认同)
  • @CarlosP这是一个非问题,因为本例中的`completionHandler'不是在并行线程中执行的.它们被添加到`mainQueue`并一次执行一个.可能有一种多线程在Cocoa的内部幕后进行处理,以便在HTTP响应到达时将块放到`mainQueue`上,但是它被抽象掉了,你不需要担心它.如果您以前在JavaScript中使用过AJAX,那么顺序执行完成处理程序的这种行为对您来说很熟悉. (2认同)