序列化NSURLConnection请求(iOS) - 使用同步请求?

时间:2011-12-29 00:06:11

标签: ios concurrency nsurlconnection grand-central-dispatch

我循环查看日期列表,并为列表中的每个日期向Web服务器发出请求。

我希望在将后续请求发送到服务器之前完全处理每个日期。为此,我使用GCD设置了一个串行调度队列。每次通过日期循环时,都会将一个块添加到队列中。

我遇到的问题是我的NSURLConnection是使用标准异步调用设置的。这导致请求不阻止任何后续请求。因此他们相互超越。

我的问题:这是一个使用同步 NSURLConnection(在调度队列中)是否合理的情况,还是有其他方法可以使用标准异步调用使其工作?

2 个答案:

答案 0 :(得分:2)

有很多方法可以做到这一点。无论选择哪种方法,启动连接都需要完成处理任务。

  1. 在添加到串行队列的每个块中,使用同步请求。只要您对同步请求的有限错误处理没有问题,这可能是您当前实施的最快解决方案。

  2. 不要使用串行队列。启动第一个异步连接并处理响应。处理完成后,启动下一个异步连接。冲洗并重复。

答案 1 :(得分:1)

我认为使用同步NSURLConnection API是一个好主意。你还有其他一些选择。一种是在NSURLConnection周围编写一个使用异步NSURLConnection API的包装器对象,这样您就可以获得异步API回调提供的好信息,包括下载进度,您可以在请求发生时轻松地继续更新UI,但是提出了自己的同步方法来做任何你需要做的事情。基本上,像:

@implementation MyURLConnectionWrapper

- (BOOL)sendRequestWithError:(NSError **)error
{
    error = error ? error : &(NSError *){ nil };

    self.finishedLoading = NO;
    self.connectionError = nil;
    self.urlConnection = [][NSURLConnection alloc] init...]

    while (!self.finishedLoading) 
    {
        [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate: [NSDate distantFuture]];
    }

    if (self.connectionError != nil)
    {
        *error = self.connectionError;
        return NO;
    }

    return  YES;
}

@end

(这些都是我的头脑,并且大量缩写,但应该给你基本的想法。)

你也可以做一些事情,例如在前一个请求的完成委托方法中触发每个请求,完全放弃使用串行调度队列:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
{
    [self sendNextRequest];
}

无论哪种方式,您都需要考虑如何正确处理连接错误。我在不同的地方使用了这两种方法并取得了很好的成功。