On iOS, can you make a synchronous network request (off the main thread) and get progress callbacks (on a separate, non-main thread)?

I have have a serial (one-operation-at-a-time) background queue that runs all of time-consuming jobs that don't need to finish right now. I do want to show progress for the download jobs though. It doesn't look like you can instantiate an NSURLConnection and configure a delegate, start synchronous connection, and then get progress callbacks.

Is there a way to make a synchronous request on that background queue (synchronous in that the job behind it doesn't start until its done), and still get setProgress: callbacks which could be sent to update a progressbar? (Callbacks would have to be on a different queue thread, since my serial queue's thread is blocked until the request is finished.)

Apple's docs for NSURLConnection say that the synchronous request is actually built on top of the asynchronous behind the scenes. Do I have to re-implement that? I need a way to block a thread until the request finishes/fails. The best leads I have so far are NSOperationQueue's waitUntilFinished method, but I don't want to start async and continually poll on the synchronous method.

NSURLConnection Discussion

A synchronous load is built on top of the asynchronous loading code made available by the class. The calling thread is blocked while the asynchronous loading system performs the URL load on a thread spawned specifically for this load request. No special threading or run loop configuration is necessary in the calling thread in order to perform a synchronous load.

解决方案

Reimplementing a synchronous request on top of an asynchronous request is not that hard. You just need to manually spin the thread's run loop until you see that the request has finished (or failed). Here's a rough example:

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]];

}

Here are the relevant NSURLConnectionDelegate methods:

- (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;

}

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐