Slide 1

Slide 1 text

SBJson 4: Don’t make me wait! Stig Brautaset ~ @stigbra

Slide 2

Slide 2 text

Who am I? Started SBJson in 2007. Compulsively tinkered with it since.

Slide 3

Slide 3 text

Fun facts 7 years on • 1012 commits • 4 major releases • 30 contributors • 3247 “stars” • 688 “forks”

Slide 4

Slide 4 text

–Every non-trivial app, ever. “Download a list of records & display them to the user.”

Slide 5

Slide 5 text

What’s more important to your users? • Time until they see the last record? • Or until they see the first?

Slide 6

Slide 6 text

The trouble with pagination • Repeated connection overhead • Records fall in the cracks between pages • Records appear on two consecutive pages

Slide 7

Slide 7 text

Download-then-parse Time to first record Time to last record

Slide 8

Slide 8 text

Chunked delivery Time to first record Time to last record

Slide 9

Slide 9 text

Multi-core chunked delivery Time to first record Time to last record

Slide 10

Slide 10 text

Relative time to first record 0 1.25 2.5 3.75 5 1 record 2 records 3 records 4 records 5 records Chunked delivery Traditional

Slide 11

Slide 11 text

NSJSONSerialisation • Supports NSStream! • But can’t do chunked delivery. • We can do better!

Slide 12

Slide 12 text

SBJson 3 • Chunked delivery since June 2011 :-) • But it was confusing and cumbersome to use… :-/ • …requiring multiple delegates chained together :-(

Slide 13

Slide 13 text

SBJson 4 • Drops category & OO interfaces • Focus on chunked delivery • Introduces a block-based interface • Built specifically for two primary use cases

Slide 14

Slide 14 text

Multi-root JSON [1,2,3] {“foo”:42} [true,false]

Slide 15

Slide 15 text

Multi-root JSON id parser =
 [SBJson4Parser
 multiRootParserWithBlock:block
 errorHandler:eh];

Slide 16

Slide 16 text

Multi-root JSON [parser parse:data("[]{")];
 // calls block(@[]) [parser parse:data("}[]"]; // next part of stream
 // calls block(@{})
 // calls block(@[])

Slide 17

Slide 17 text

Multi-root JSON [parser parse:data("[]{")];
 // calls block(@[]) [parser parse:data("}[]"]; // next part of stream
 // calls block(@{})
 // calls block(@[])

Slide 18

Slide 18 text

Compromise: “garbage after JSON” []**xx block(@[])
 errorHandler(…)

Slide 19

Slide 19 text

–Johnny Appleseed “What if I am using a 3rd-party API that just gives me a long list?”

Slide 20

Slide 20 text

Root array chunks [ [1,2,3], {“foo”:42}, [true,false] ]

Slide 21

Slide 21 text

Unwrap the root array! id parser =
 [SBJson4Parser
 unwrapRootArrayParserWithBlock:block
 errorHandler:eh];

Slide 22

Slide 22 text

Unwrap the root array! [parser parse:data("[[],{")];
 // calls block(@[]) [parser parse:data("},true]")];
 // calls block(@{})
 // calls block(@(YES))

Slide 23

Slide 23 text

Unwrap the root array! [parser parse:data("[[],{")];
 // calls block(@[]) [parser parse:data("},true]")];
 // calls block(@{})
 // calls block(@(YES))

Slide 24

Slide 24 text

Compromise: Corrupted / incomplete JSON [
 {},
 [],
 ***###$#”>P block(@{})
 block(@[])
 errorHandler(…)

Slide 25

Slide 25 text

Unwrapping is for root-level arrays only!

Slide 26

Slide 26 text

SBJson’s Blocks SBJson4ValueBlock block = ^(id obj, BOOL *stop) {
 if (some_condition) {
 *stop = YES;
 } else {
 // do something with obj
 }
 };

Slide 27

Slide 27 text

SBJson4ParserStatus switch ([parser parse:data]) {
 case SBJson4ParserStopped:
 case SBJson4ParserComplete:
 NSLog(“Done!");
 case SBJson4ParserWaitingForData:
 break;
 case SBJson4ParserError:
 NSLog(@"Ouch, I'm hurt!");
 break;
 }

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

Two CocoaPods! To allow both version 3 and 4 in the same application.

Slide 30

Slide 30 text

http://www.flickr.com/photos/dullhunk/202872717/