JordanMazurke
JordanMazurke

Reputation: 1123

Architectural approach to HTTP communications and the parsing of returned JSON in iOS

Good evening guys,

My question is more of an engineering/design pattern approach than specifically technical.

I am developing an app that requires lots of interaction with a remote API returning JSON objects. The retrieval, parsing and utilisation of the data is not a problem and is working very smoothly. I am wanting to get some direction on the best design approach for this sort of scenario.

I will explain what I have so far (in pseudo code and declarations) and see if you can help:

  1. A HTTP Fetcher class implementing the necessary NSURLConnection delegate methods. I initialise the class with the callback method selector like so for returning to the calling class on completion

    @implementation HTTPFetcher{
        - (id)initWithUrlRequest:(NSURLRequest *)aRequest receiver:(id)aReceiver action:(SEL)aReceiverAction
        {
         //set the member variables etc..
        }
    
        //all NSURLConnection delegate methods
    
        - (void)connectionDidFinishLoading...
        {
            [receiver performSelector:action withObject:self];
        }
    }
    
  2. I then have a Singleton HTTPController class for calling the HTTPFetcher:

    - (void)postWithRequestString:(NSString *)aRequestString
    {
        [urlRequest setHTTPBody:[aRequestString dataUsingEncoding:NSUTF8StringEncoding]];
    
        fetcher = [[HTTPFetcher alloc]initWithUrlRequest:urlRequest receiver:self action:@selector(receivedDataFromService:)];
        [fetcher start];
    }
    
    - (void)receivedDataFromService:(HTTPFetcher *)aFetcher{
        //handle the received data and split the parent object into an NSMutableDictionary
    }
    

Now this approach works fantastically well for the app I have especially given the separate entities that I have to model (I will basically have a Singleton HTTPController for each entity).

My issue is where to handle the custom parsing of the JSON. Currently, I am doing the parsing the in ViewController where the data is required but this is too close to the source and needs to be abstracted out further but I am unsure how.

Should I include the methods to facilitate the parsing within the Singleton classes or should I create further controllers for parsing actions?

I look forward to hearing from you

Thanks

Upvotes: 1

Views: 376

Answers (2)

user244343
user244343

Reputation:

I would recommend you build on an existing JSON parsing library, in particular John Engelhart's JSONKit, considering it's arguably the highest performance JSON parsing library out there for iOS. Saves you implementing custom JSON parsing at all, but especially saves you implementing code which turns out to be too slow for your needs and then you will need to iteratively refine it until it gets fast enough for you to use.

For HTTP requests, I know you've implemented the behaviour already, but you might want to investigate ASIHTTPRequest or AFNetworking as general purpose networking libraries which have a reputation for being quite robust. Note AFNetworking uses the above JSONKit library for JSON parsing.


The way ASIHTTPRequest (the library I use in my projects) works is by using a delegate object implementing the protocol ASIHTTPRequestDelegate, which you assign after creating a request with a URL. There's a global network queue which is just an NSOperationQueue, and that handles asynchronous or multiple concurrent active requests.

You can setDelegate: for the object to start checking whether your delegate has implemented any of the methods at different points, such as didReceiveData: or requestDidFinish: by default, but you can also set a custom selector path to check by using the methods for individual operations (setDidFinishSelector:@selector(downloadComplete:)).

What you could do when, for example, the didReceiveData: callback happens, is pass the newly received data into a buffer stored in a wrapper class for an ASIJSONRequest (or use AFNetworking, which already encapsulates this). When the buffer is such that there is a complete JSON object in there which can be parsed correctly, then you call out to JSONKit to do the grunt work and then maybe send another callback yourself to an ASIJSONRequestDelegate for didReceiveData:, but now the data is in a format which is readable by the rest of your application.


Another method of using ASIHTTPRequest is with blocks. There is support for setting a completion block for a request, a block that is called when data is received, etc. For this design pattern you don't even need a wrapper class, just set the code block up to do the parsing itself and return any new data parsed to its desired destination.

Upvotes: 1

hotpaw2
hotpaw2

Reputation: 70733

One possibility would be for the View or view controller to ask a Model object for any state that it needs (including stuff from a remote server). The Model object would be told when there was any new data from the server, and it could then call any required data munging routines required to update its internal state (converting plists or json into a more canonical dictionary format, for instance).

Upvotes: 1

Related Questions