views:

903

answers:

2

I am currently building my Core Data model, which I would like to sync between the Mac and iPhone versions of my application.

I will be using Bonjour for device discovery, etc but I have a question regarding the data sync part of the problem.

So far I have added a UID and modification timestamp to each object that will be involved in syncing, so I should be able to match up objects and detect which ones have changed.

Are there any good links, resources out there regarding writing sync code for this type of situation, i.e. syncing records between two instances of a model?

Sync is a problem with quite a few edge cases which have been solved many times by people in the past, so I was expecting to find some info on the subject but all I can find are links to Apple's SyncServices (which doesn't exist on iPhone) and some MS sync technology.

I'm really looking for general theory so I can implement it myself, not necessarily a ready-made solution.

+5  A: 

The SyncML specification may be of help, but it's quite hard to read and obviously biased towards SyncML.

I've had to implement this for Task Coach, so here are a few ideas:

A modification flag is enough, a timestamp doesn't really provide much more information. Typically, my objects are in one of these states:

  • None
  • New
  • Deleted
  • Modified

The following transitions happen when the object is modified:

  • None -> Modified
  • New -> New
  • Deleted -> (should not happen)
  • Modified -> Modified

and the following ones when it is deleted:

  • None -> Deleted
  • New -> Actually deleted (it may be removed from storage)
  • Deleted -> (should not happen)
  • Modified -> Deleted

When synchronizing, the device first sends to the desktop all objects with a status different than None. The desktop asks the user to resolve conflicts if one of these has a status != None on its side. In any case, the object goes into state None on the device, or is deleted from storage if its state was Deleted.

Then, the desktop sends its own changes to the device. There are no conflicts possible since all objects are in state None on the device. Objects on the desktop go into state None or are deleted from storage as well, and sync is over.

There are two types of possible conflicts, depending on the device/desktop states:

  • modified/deleted. If the user chooses to trust the device, the desktop object is replaced with the device one; else, the desktop does nothing and keeps the deleted state, so that the object will be removed from the device in phase 2.
  • deleted/modified: If the device wins, the object is actually deleted from the desktop. Else, the object goes into state New on the desktop so that it is restored on the device in phase 2.
  • deleted/deleted: Duh. Just remove it from storage.
  • modified/modified: The user decides which values to keep, maybe on a field by field basis. The state stays to Modified on the desktop so that these choices are propagated back to the device in phase 2.

Some conflicts may be avoided if the Modified state is kept for each field, so that for instance an object with a modified Subject on the device and modified Summary on the desktop will not trigger a conflict.

You may take a look at the code for Task Coach for an example (SVN repository on SourceForge, it has both the desktop app in Python and the iPhone app). Actually, in this case I decided to use a simpler approach; I don't keep track of the state on the desktop. After phase 1 (device to desktop), I just make a full replacement of objects on the device with the ones on the desktop. Thus, there are no conflicts (the device always wins).

Obviously, this only works between two fixed devices; if you want to synchronize with several phones/desktop apps, you have to assign a unique ID to each and keep different states for different devices/apps. This may begin to get hairy.

HTH

fraca7
The timestamp helps distinguish between concurrent edits on two devices. If you just use a boolean 'modified' flag, then it's hard to know which is the most recent data.
AlBlue
Thanks fraca7, this was just the kind of thing I'm after. I will look into the SyncML docs as well to see if they go into this kind of detail. Any other suggestions anyone?
Charles Gamble
AlBlue: that is if you want some kind of automatic conflict resolution, but I'd rather ask the user. If both records were modified, he should be the one who decides.
fraca7
After almost a year I think fraca7's reply most closely answers the question, although in this case I will be hoping that Marcus Zarra's ZSync framework will handle most of it for me. Thanks all.
Charles Gamble
+2  A: 

Marcus Zarra created a framework called ZSync to simplify synching iPhone/iPad apps to their Mac counterparts. Take a look at it, it may help solve the problem.

John Wang
Thanks John, I have been following ZSync for a while, I'm just waiting to see how it fares in a real-world app first. It looks like a great project though and could fit my needs very well.
Charles Gamble
Pretty sure MoneyWell for iPhone is using ZSync now (http://nothirst.com/moneywell/iphone/)
petert