As I built a more advanced app using Three20, I realized that it would be great to be able to persist to a database to make loading quicker when state on the server is unchanged. I needed some pretty basic Core Data integration in my app, and it was a little annoying that Three20 didn't have a Core Data-backed implementation of TTModel built into it. It seems like a lot of people want this, but there isn't any good post about it I could find. Jeff Verkoey, who currently maintains Three20, started writing a Core Data based tutorial but didn't get around to actually doing much with it. And there are a few threads in the Three20 Google group but nothing too comprehensive.
Having built this for my app, I figured I would post some more concrete information here for others who might find it helpful. I really want to just contribute a clean cut of this code as a
TTCoreDataModel
with unit tests to the Three20 source, but I don't have the luxury to spend time on it currently.So here's a quick step-by-step on how to modify your existing Three20 based app to add basic Core Data support. The specific example I use fetches data from a server using
TTURLRequestModel
and writes it out to SQLite using Core Data entities. When displaying data to the user, it fetches data from Core Data using a NSFetchedResultsController,
which efficiently interacts with Core Data.Step 1:
Add CoreData.framework to your list of dependencies. Then, add the Core Data stack. Usually, you would do this in the AppDelegate. Jeff's AppDelegate files have this implemented, if you want an example. In my case, I wanted different databases for different Models, so I had these in my TTModel implementations.
Add CoreData.framework to your list of dependencies. Then, add the Core Data stack. Usually, you would do this in the AppDelegate. Jeff's AppDelegate files have this implemented, if you want an example. In my case, I wanted different databases for different Models, so I had these in my TTModel implementations.
Step 2:
Create your model. Add a new file of type "Data Model" in XCode (available in the 'Resource' section). Make sure the .xcdatamodel file gets added to your Target so that it's compiled into your binary. Look here for information on using the modeling tool. Once you've created your model, import the code for the Entity objects into your project. Now you're ready to start using Core Data.
Step 3:
Update your TTURLRequestModel implementation. Let's assume you're simply downloading some JSON and want to write it out to Core Data as an Entity you created in Step 2. Update your
(void)requestDidFinishLoad:(TTURLRequest*)request
implementation of TTURLRequestDelegate
as follows:A few notes about the code above:
DBResource
is my simple entity containing an "id" and a "name".- The
NSAutoreleasePool
helps clean up memory allocated in this tight loop here -reset
ing the context makes sure that the data faults in as needed instead of staying in memory when you read it using theNSFetchedResultsController
Step 4:
In your
TTTableViewDataSource
implementation, create a NSFetchedResultsController
and configure it to fetch your Entities as needed. Then, override the (id)tableView:(UITableView*)tableView objectForRowAtIndexPath:(NSIndexPath*)indexPath
method to return a TTTableItem
built using the Entity you fetched from Core DataNow, your TTTableViewDataSource is configured to read results from the DB you created and display them in your view. Remember that
tableViewDidLoadModel
can be called multiple times, so clean up any previously allocated NSFetchedResultsController
if you need to.Step 5:
Implement your logic to delete/update your Core Data entities. Depending on how your app uses data persistence, you want to ensure that you update/delete your entities from Core Data. For instance, if you always want to fetch data from the server and load them into Core Data on first run, then update Step 3 to first delete all entities. If you wish to show local data when available but fetch when not, then update Step 3 to not hit the server before checking locally. When deleting entities, remember that Core Data only lets you delete a single entity at a time (so you must fetch all and loop through each to delete it). If you want
DROP TABLE ...
semantics you're going to need to maintain different NSManagedObjectContent
and NSPersistentStoreCoordinator
for each such table, and then simply delete the database file.So, this isn't too hard really. Assuming you're familiar enough with building your Three20 app, my notes above should help you get started with integrating Core Data into your app. My app uses a
TTSectionedDataSource
, and with a few tweaks to NSFetchedResultsController
it's simple to do that too.
11 comments:
I think a lot of people have been looking forward to more guidance on this topic. Would you consider posting a sample project, especially with TTSectionedDataSource? Thanks!
I'm having a problem using this with the TTSectionedDataSource. Can you post a sample project for TTSectionedDataSource?
Great article. Do you have a sample project? Thanks!
I'd like to see a sample too :)
Yes a sample project would be really awesome.
Thanks anyway for sharing this tutorial
It will be fabulous if you post the sample code for integrating coredata with Three20.
Your work can be help to lot of newbies....
Is there a sample project available?
Nice guide. May I ask how do you implement NSFetchedResultsControllerDelegate methods with TTTableController?
Great article
you should also look at http://restkit.org/
RestKit has some three20 integration and a nice way to integrate remote REST implementations directly into Core Data with a simple mapper. So you can just worry about your schema and leave all the crazy Model handling to RestKit, Core Data and three20.
Post a Comment