Three20 JSON datasource implementation

Three20 is a nice iPhone library, but the documentation is pretty much limited to the TTCatalog example app code…one thing that’s left as an exercise for the reader is the implementation of a datasource that fetches its data over the network and how it interacts with its associated TTTableViewController.

One approach to this problem is to subclass a canned datasource, which gets us a bunch of stuff for free right off the bat:

@interface MyDataSource : TTListDataSource<TTURLRequestDelegate> {
 @private
  BOOL _loading;
  BOOL _loaded;
}

You’ll want to provide meaningful implementations of accessors like loadedTime:, isLoading:, isLoadingMore:, isLoaded:, etc. Your controller will query the datasource using those selectors to know what state to show (e.g. loading, error, data, no data).

Write a load:nextPage: implementation that hits the network:

- (void)load:(TTURLRequestCachePolicy)cachePolicy nextPage:(BOOL)nextPage {
  TTURLRequest *request =
   [TTURLRequest requestWithURL:@"http://test.com/test.json" delegate:self];

  request.cachePolicy = cachePolicy;
  request.response = [[[TTURLDataResponse alloc] init] autorelease];
  request.httpMethod = @"GET";
  [request send];
}

Write a requestDidFinishLoad: implementation that pulls JSON out of the response (maybe using Stig Brautaset’s very nice JSON framework) and let your controller know that data’s available via dataSourceDidFinishLoad:.

- (void)requestDidFinishLoad:(TTURLRequest*)request {
  TTURLDataResponse *response = request.response;
  NSString *json = [[NSString alloc] initWithData:response.data encoding:NSUTF8StringEncoding];

  // Load up self.items with json data however you'd like

  [json release];

  _loading = NO;
  _loaded = YES;  

  [self dataSourceDidFinishLoad];
}

Don’t forget to implement requestDidStartLoad:, request:didFailLoadWithError:, and requestDidCancelLoad: and have them notify any interested delegates of the request’s status. Here’s an example:

- (void)request:(TTURLRequest*)request didFailLoadWithError:(NSError*)error {
  _loading = NO;
  _loaded = YES;
  [self dataSourceDidFailLoadWithError:error];
}

In your controller, createDataSource: might look like this:

- (id<TTTableViewDataSource>)createDataSource {
  MyDataSource *dataSource = [[[MyDataSource alloc] init] autorelease];
  [dataSource.delegates addObject:self];
  [dataSource load:TTURLRequestCachePolicyDefault nextPage:NO];
  return dataSource;
}

Have fun out there.

Update, April 11 10:30 AM EDT
I’ve added a new post with a downloadable example project and (finally) cleaned up the above code. I apologize for previous typos; I really should make sure the code I post actually compiles instead of writing/tweaking it in a wordpress edit window.

Update, October 3 9:30 AM EDT
It’s come to my attention that some people are still using this code – please don’t! It was based on three20 as it existed back in March/April 2009 and is now very much out-of-date. If you’re looking for current and correct three20 sample code, Keith Lazuka’s github has what you need. Thanks!

This entry was posted in iPhone. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

7 Comments

  1. dd
    Posted April 4, 2009 at 11:58 pm | Permalink

    Nice write up. Do you have a full example of a json datasource you’d be willing to post?

  2. dd
    Posted April 5, 2009 at 10:11 am | Permalink

    Do you have a complete datasource example that you’d be will in to post? Thanks!

  3. Rob Morgan
    Posted April 5, 2009 at 10:42 pm | Permalink

    Hey,

    Thankyou very much for the helpful article. I’ve followed it with one of my projects but I’m currently getting an error in the createDataSource method.

    When I add the line [dataSource.delegates addObject:self], the compiler complains with: “error: request for member ‘delegates’ in something not a structure or union”.

    I’m a bit unsure what this means. I don’t have a delegates property in my DataSource but I didn’t notice one in your tutorial either.

    Cheers,

    Rob

  4. Posted April 6, 2009 at 8:31 pm | Permalink

    Hey thanks a ton for the tutorial!!

    My only confusion is lies with [dataSource.delegates addObject:self]

    My app says “request for member delegates is something not a structure… etc etc”

    What do i need to do?

  5. Mark
    Posted April 7, 2009 at 11:27 am | Permalink

    Sorry about that – was careless in posting the code snippets and the protocol bits were interpreted as HTML :(

    Anyway, I’ve updated the examples and will try to post a full example project later tonight or tomorrow (busy at work at the moment). For now, see if your problems are solved by extending TTListDataSource like this:

    @interface MyDataSource : TTListDataSource<TTURLRequestDelegate>

  6. Posted April 11, 2009 at 1:28 am | Permalink

    Hey man any chance you could post that example? Would be a huuuuge help.

    Thanks

  7. Mark
    Posted April 11, 2009 at 10:12 am | Permalink

    Matt, I’ve added a new post which includes a downloadable example project. HTH

One Trackback

  1. By Three20 Gets Documentation « Transmogrify on December 18, 2009 at 5:02 pm

    [...] techniques consisted of searching the web for blog posts (most of them outdated like mine since Three20 has gone through some pretty big refactorings), reading the source, and [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>