Search code examples
iosnsurlconnectiondispatch

What's the difference between performing an NSURLRequest and responding to delegates as opposed to using dispatch_async?


I'm trying to get my head around a asynchronicity; dispatch, multiple threads, run loops etc etc.

What's the difference between:

1) creating an NSURLRequest and NSURLConnection in a given method, and having it execute and us responding to the delegate methods (didReceiveResponse, didReceiveData, connectionDidFinishLoading, etc), and

2) creating a block and having it dispatch_async ?

With the first method it seems great that I have access to the delegate methods (do I still have access to those using dispatch?), and execution of the delegate methods are actioned when fired (or close to it?)

With the block/dispatch method, I'm guessing the block is processed synchronously within it's thread? And then comes back to the main thread to process the results? Example code I've been looking at:

    dispatch_async(kBgQueue, ^{
    NSData* data = [NSData dataWithContentsOfURL: 
      kLatestKivaLoansURL];
    [self performSelectorOnMainThread:@selector(fetchedData:) 
      withObject:data waitUntilDone:YES];
});

So, the "self performSelector...." is performed AFTER the data is received? (what I meant before with synchronously - maybe the wrong term). And the next line of the block sends us back to the main thread.

What is the purpose of, or why is there a "waitUntilDone:YES"? Is it because if it's not there, other stuff could happen NOT in the main thread?

Is the first method above still only performed on the main thread?

and finally, what are the pros and cons of each in the case of a JSON query to a web page? Is there any great benefit of one method over the other?


Solution

  • 1) When you use a NSURLConnection, either in your main thread or say in a NSOperation, you have full control of stopping it at any point, and tracking its progress. What you get back are delegate methods when various things happen, but you're not sitting and waiting for something to complete. If you want to stop it at anytime, you send it cancel, then you can release (or nil) it and forget about it.

    2) So look at this. If you did this call in the main thread, it would wait until it succeeds or fails. Once started, it has to run to success or failure. This would block your UI if in the main thread. Put it in a block and run it on some other thread, and the same thing will happen - the chosen thread will block until the method ends. The use of 'self' to send the result will retain self. So if self is say a UIViewController, then even if you pop it (thinking its going to get removed), it stays around until this method completes, doing heaven knows what. This usage is very dangerous and may work often but fail catastrophically when a device has a crappy inet connection (for example).

    The wait until does is to synchronize threads. If you want to know that the method has been run on the main thread, and only then proceed, use YES. If you just want the method queued and you're done (like in this case) you would just use NO.

    The method will for sure be on the main thread - this Apple promises you with this method.

    3) JSON

    The majority of users I know use NSURLConnections from NSOperations or blocks. Operations can be cancelled (which would then cancel the connections) - so you can handle getting a 'Back' button press no matter how much is going on. If the query fails you can look at the html status (did you get a 400 or 500 error? a timeout? etc)

    There is an open source project on github, hardly 200 lines of code, that provide an elegant and easy to use helper class to run operations (with demo code): /NSOperation-WebFetches-MadeEasy. I have personally used this code in over 8 apps still in the store with great success - a single OperationsRunner often has hundreds of fetches going on simultaneously, and the app has multiple classes running OperationsRunners at the same time.

    If you process the JSON in the NSOperation, you will get real speedups on devices with multiple cores.