Stretch
Stretch

Reputation: 3759

Optimal way of syncing Core Data with server-side data?

I have what I would presume is a very common situation, but as I'm new to iOS programming, I'm not sure of the optimal way to code it.

Synopsis:

I have data on a server which can be retrieved by the iPhone app via a REST service. On the server side, the data is objects with a foreign key (an integer id number).

I'm storing the data retrieved via REST in Core Data. The managed objects have an "objId" attribute so that I can uniquely identify the managed objects in the rest of my code.

My app must always reflect the server data.

On subsequent requests made to the server:

my solution - and question to you

To get things going in my app, I made the easiest solution of deleting all objects in Core Data, then adding all new objects in, created with the latest server side data.

I don't think this is the best way to approach it :) As I progress on with my app, I now want to link up my tableview with NSFetchedResultsController, and have realised that my approach of deleting everything and re-adding is not going to work any more.

What is the tried and trusted way of syncing Core Data with server side data?

Do I need to make a fetch request for each object id I get back from the server, and then update the object with the new data?

And then go through all of the objects in core data and see which ones have not been updated, and delete those?

Is that the best way to do it? It just seems a little expensive to do a fetch for each object in Core Data, that's all.

Pseudo code is fine for any answers :)

thanks in advance!

Upvotes: 3

Views: 1078

Answers (1)

Jody Hagins
Jody Hagins

Reputation: 28339

Well, consider your download. First, you should be doing this in a background thread (if not, there are lots of SO posts that talk about how to do that).

I would suggest that you implement what makes sense first, and then, after you can get valid performance data from running Instruments, consider performance optimization. Of course, use some common sense on "easy" performance stuff (your design can take care of the big ones easily enough).

Anyway, get your data from the online resource, and then, for each object fetched, use the "unique object id" to fetch the object from core data. You know there is only one object with that ID, so you can set fetchLimit to 1 on your fetch request. You can also configure your "object id" attribute to be an INDEX in the database. This way, you get the fastest search from the underlying database, and it knows to stop looking once it finds your one object. This should be pretty snappy.

Now you have your object. Change any attributes necessary. Save, rinse, and repeat.

Furthermore, for several reasons, you may want to know when objects were last updated. I'd suggest adding a timestamp to each object that gets changed with the current time every time an object is changed. This will also help in deleting objects. Since your online database does not tell you which objects are deleted, you must have some way to know that an item is "old and no longer needed."

An easy way to do this is to remember the time you started your update. After processing all objects from the download, you now have a way to find all the objects that were deleted from the online database. Basically, any object with a "last update" timestamp before the time you began the update should be removed (since they were not added or modified in the last update). You can also index the database on this field, which will make finding those objects faster - unless your database is huge, I'd wait to see what Instruments has to say about this one though.

Upvotes: 3

Related Questions