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. 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; not
constrained by the Pecha Kucha format, I was able to add some slides to
address feedback from that talk. The slides
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. (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:.
  2. By unwrapping a root array and feed every top-level element
    inside the root to your application, one by one. See
    +unwrapRootArrayParserWithBlock:errorHandler:.

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‘s
connection:didReceiveData: or NSURLSessionDataDelegate‘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.

Print Friendly

Leave a Reply