Wednesday, March 26, 2014

SBJson4: Don’t make me wait! (… for my content)

Last week, I went to give a talk about SBJson (an Objective-C library for JSON parsing and writing) to the London iOS Developer Group [1] . They meet on the first Wednesday of every month at the Regent Street Apple store for technical talks, followed usually by a social event at a nearby pub. In my talk, I tried to explain why I think SBJson is still relevantâ€"even after Apple added native JSON support to iOS 5 in 2011.

Essentially, I gave a slightly extended version of a talk I had previously given at Cocoa Kucha 2 [2] ; not constrained by the Pecha Kucha format, I was able to add some slides to address feedback from that talk. The slides [3] for the talk are available. Unfortunately, this version was not filmed, but there is video available for the previous version at Cocoa Kucha 2 here [4] . (The audio is of poor quality: my apologies.)

The rest of this post covers the gist of my talk.

Downloading long lists

Have you ever written an app that downloads a list of records? I believe this is a common theme in many apps. If it’s a long list, the app may appear to hang, “go blank”, or show a loading screen before displaying anything to the user.

One popular work-around for downloading long lists on slow connections (think 3G or EDGE) is to use pagination. That is, split up the list into multiple parts and download each part separately, to avoid your users having to wait too long before they see anything at all.

Problems with pagination

However, this chopping up of the data can introduce inconsistencies, particularly in fast-moving data, because you can either have the same item in two pages, or you may miss items. You also then have to suffer a connection overhead for each page, rather than just once for the list; on iOS, this overhead can be significant.

I believe it may not always be necessary to put up with the above trade-offs. I think users usually care about how long it takes until they see the first record, not until the last record. With SBJson, you can get all records in one big list, but start parsing the stream and feeding records to your users before the download of the full list has finished. And since SBJson is not a pure event-based parser either, you can get high-level documents; not a callback for every bool, string, or number in the source JSON.

How SBJson can help

SBJson supports two different types of input:

  1. By downloading a stream of not one, but many stand-alone JSON documents. (Twitter provides streams of this type.) See +multiRootParserWithBlock:errorHandler: [5] .
  2. By unwrapping a root array and feed every top-level element inside the root to your application, one by one. See +unwrapRootArrayParserWithBlock:errorHandler: [6] .

To see benefits for your users, your app might require a bit of re-engineering. You would typically push the parsing into the download delegate, so either in NSURLConnectionDataDelegate [7] ‘s connection:didReceiveData: or NSURLSessionDataDelegate [8] ‘s URLSession:dataTask:didReceiveData: methods. Essentially, you feed data portions directly to the parser instead of using an accumulator like this:

- (void)URLSession:(NSURLSession *)session            dataTask:(NSURLSessionDataTask *)dt      didReceiveData:(NSData *)data {       switch ([parser parse: data]) {         // handle various returns here...     }  }  

There are some caveats to parsing a stream of documents, particularly when unwrapping root arrays. Normally, a JSON parser would parse and validate a complete document; however, that forces you to have seen the entire document before parsing so when parsing streams we have to relax that requirement.

In closing: if you need to parse large (or slowly arriving) chunks of JSON, you may be able to use SBJson to improve the responsiveness of your application.

Links
  1. ^ London iOS Developer Group (lanyrd.com)
  2. ^ Cocoa Kucha 2 (blog.cocoapods.org)
  3. ^ slides (speakerdeck.com)
  4. ^ here (vimeo.com)
  5. ^ +multiRootParserWithBlock:errorHandler: (cocoadocs.org)
  6. ^ +unwrapRootArrayParserWithBlock:errorHandler: (cocoadocs.org)
  7. ^ NSURLConnectionDataDelegate (developer.apple.com)
  8. ^ NSURLSessionDataDelegate (developer.apple.com)

No comments:

Post a Comment