3

I'm developing a network based iOS app that downloads json data from the server and processes it. Both the downloading task and processing task can take a significant time to complete, So I don't want to perform either on the main thread.

I think there are 2 ways to do this:

  1. Perform asynchronous loading using NSURLConnection and in the didFinishLoading method use GCD (say) to do the processing in background.

  2. Use GCD's dispatch_async (say) to start work in background and use NSURLConnection's sendSynchronousRequest:returningResponse:error to download the data synchronously, Do the processing of the data, And call UI updates on the main thread.

I think the 2nd method would be easier to write and would produce cleaner code, Especially if one "download/process data" task involves multiple sequential service calls for data download. So rather than execution going like:

main (start) -> background (download) -> main (NSURLConnectionDelegate method) -> background (data processing) -> main (UI update)

We would have:

main (start) -> background (download) -> background (data processing) -> main (UI update) which seems to be cleaner to me.

I found 2 similar questions: Good pattern for Internet requests with Grand Central Dispatch? And
NSURLConnection and grand central dispatch

And the answers to both seem to suggest using something conceptually similar to method 1.

Is there no proper way to achieve what's described in method 2?

Thanks in advance!

Community
  • 1
  • 1
wingman123
  • 61
  • 1
  • 4
  • 1
    Have a look at [AFNetworking](https://github.com/AFNetworking/AFNetworking). – Mike D Mar 07 '13 at 04:50
  • @MikeD, What AFNetworking can additionally do here is performing the JSON parsing in background, isn't it? What if I need to perform expensive processing on the parsed JSON objects? I think what I'm looking for is more of a design pattern than a framework :) – wingman123 Mar 07 '13 at 05:04
  • I am always using second approach but one advantage with first approach is prior to ios 6 if you want to timeout post request with less than 240 secs, its possible by canceling asynchronous connection. – prasad Mar 07 '13 at 05:32
  • Why not make it easier on yourself and use `sendAsynchronousRequest:queue:completionHandler:`? You can put a `dispatch_async` in the completionHandler to do the processing on a background thread. – Christopher Pickslay Mar 07 '13 at 20:17
  • @ChristopherPickslay, Suppose we need to make multiple web service calls to complete one "task". Then we'd have to write blocks within blocks. In addition, things can get complicated when you have to go through an object hierarchy to do the processing. I'm not saying that this cannot be done, but the second approach seems easier to implement. I'm trying to find out whether there are any reasons why I shouldn't do things that way. – wingman123 Mar 08 '13 at 02:42

1 Answers1

0

I would not be inclined to pursue option #2. Although it enjoys a certain simplicity, sendSynchronousRequest does not afford progress updates during the download, the ability to cancel the request (and other more complicated scenarios). A NSURLConnectionDataDelegate approach gives you far more control over the network requests.

This question presumes GCD-based patterns, but I think operation queue patterns merit consideration. You can marry the control offered by the NSURLConnectionDataDelegate methods with cancelable operations that encapsulate the network request. When you start to get more sophisticated, you can start employing concurrent requests, but also constrain the degree of concurrency (e.g. not more than five concurrent requests).

I'd suggest taking a look at AFNetworking. Maybe you don't want to use that framework, but I'd still take a look at the operation-queue-based patterns it employs. I'd personally use that pattern over either of the aforementioned GCD approaches.

Rob
  • 415,655
  • 72
  • 787
  • 1,044