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

序列化NSURLConnection请求(iOS)-是否使用同步请求?,ios,concurrency,nsurlconnection,grand-central-dispatch,Ios,Concurrency,Nsurlconnection,Grand Central Dispatch,我正在循环浏览一个日期列表,并为列表中的每个日期向web服务器发出请求 我希望在将后续请求发送到服务器之前完全处理每个日期。为此,我使用GCD设置了一个串行调度队列。每次通过日期循环时,都会向队列中添加一个块 我遇到的问题是,我的NSURLConnection是使用标准异步调用建立的。这会导致请求不阻止任何后续请求。因此,它们正在相互超越 我的问题:在这种情况下,使用同步NSURLConnection(在调度队列中)对我来说有意义吗?还是有其他方法可以使用标准异步调用使其工作 我认为使用同步NS

我正在循环浏览一个日期列表,并为列表中的每个日期向web服务器发出请求

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

我遇到的问题是,我的NSURLConnection是使用标准异步调用建立的。这会导致请求不阻止任何后续请求。因此,它们正在相互超越


我的问题:在这种情况下,使用同步NSURLConnection(在调度队列中)对我来说有意义吗?还是有其他方法可以使用标准异步调用使其工作

我认为使用同步NSURLConnection API是一个好主意。你还有一些其他的选择。一种是围绕使用异步NSURLConnection API的NSURLConnection编写一个包装器对象,这样您就可以获得异步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];
}

无论哪种方式,您都需要考虑如何适当地处理连接错误。我已经在不同的地方成功地使用了这两种方法。

我认为使用同步NSURLConnection API是一个好主意。你还有一些其他的选择。一种是围绕使用异步NSURLConnection API的NSURLConnection编写一个包装器对象,这样您就可以获得异步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];
}

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

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

  • 在添加到串行队列的每个块中,使用同步请求。考虑到您当前的实现,这可能是最快的解决方案,只要您对同步请求的有限错误处理还满意

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


  • 有很多方法可以做到这一点。无论您选择何种方法,启动连接都需要与处理任务的完成相关联

  • 在添加到串行队列的每个块中,使用同步请求。考虑到您当前的实现,这可能是最快的解决方案,只要您对同步请求的有限错误处理还满意

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

  • 感谢两位(安德鲁·马德森和Xjones)的快速回复。听起来同步通话对我来说很有效。(我希望避免它和随之而来的额外维护工作。)关于端到端连接电话,这是可能的,但我不确定在我的情况下是否值得。与其管理调度队列,不如让我管理一个日期队列。我认为设置同步呼叫会更简单。感谢两位(安德鲁·马德森和Xjones)的快速回复。听起来同步通话对我来说很有效。(我希望避免它和随之而来的额外维护工作。)关于端到端连接电话,这是可能的,但我不确定在我的情况下是否值得。与其管理调度队列,不如让我管理一个日期队列。我认为设置同步调用会更简单。