在iOS上,你可以发出同步网络请求(但不是在主线程上)并仍然获得进度回调(在一个单独的非主线程上)?

时间:2012-07-13 13:53:26

标签: ios nsurlconnection grand-central-dispatch

在iOS上,您是否可以发出同步网络请求(在主线程之外)并获取进度回调(在单独的非主线程上)?

我有一个串行(一次一个操作)后台队列,它运行所有耗时的工作,现在不需要完成正确。我确实希望显示下载作业的进度。看起来您不能实例化NSURLConnection并配置委托,启动同步连接,然后获取进度回调。

是否有办法在该后台队列上发出同步请求(同步请求后面的作业在完成之前不会启动),并且仍然可以发送setProgress:个回调来更新进度条? (回调必须在不同的队列线程上,因为我的串行队列的线程被阻塞,直到请求完成。)

Apple's docs for NSURLConnection说同步请求实际上建立在幕后异步之上。我必须重新实施吗?我需要一种方法来阻止线程,直到请求完成/失败。到目前为止,我所拥有的最佳线索是NSOperationQueue的{​​{1}}方法,但我不想在同步方法上启动异步并不断轮询。

  

NSURLConnection讨论

     

同步加载构建在类可用的异步加载代码之上。当异步加载系统在专门为此加载请求生成的线程上执行URL加载时,将阻止调用线程。调用线程中不需要特殊的线程或运行循环配置来执行同步加载。

1 个答案:

答案 0 :(得分:7)

在异步请求之上重新实现同步请求并不难。您只需手动旋转线程的运行循环,直到您看到请求已完成(或失败)。这是一个粗略的例子:

NSURLRequest *downloadRequest = [NSURLRequest requestWithURL:queryURL];
// Start the download and wait until it finishes
self.downloadFinished = NO;
self.downloader = [NSURLConnection connectionWithRequest:downloadRequest delegate:self];

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

以下是相关的NSURLConnectionDelegate方法:

 - (void)connectionDidFinishLoading:(NSURLConnection *)connection;
 {
    self.downloadFinished = YES;
 }

 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
 {
    NSLog(@"An error occurred: %@", error);
    self.receivedData = nil;
    self.downloadFinished = YES;
 }