I am working on syncing data between the client and a server. I am using MagicalRecord
(a Core Data wrapper) for storing the data on the client. I have an entity called Dirty
that contains a single attribute called dirty
. This represents if there were changes on the client that have not been pushed up to the server yet. dirty
gets set to [NSDate date]
anytime an attribute is set on the class (of course, when setting dirty
, the correct value is set). Every other entity created on the client inherits from Dirty
. The idea is that we won’t fetch new data from the server until all client data has been pushed up (only fetch new data if all entities have dirty == nil
).
When importing data from the server (using +[NSManagedObject MR_importFromObject:inContext:
), each entity’s dirty
attribute gets set to nil
(because the client is up-to-date with the server).
Right before a save is kicked off (inside the +[MagicalRecord saveWithBlock:completion:]
save block), dirty
is still nil
. However, in the completion block, fetching the entity that was just saved (on the main thread) has a value for dirty
.
During the save, the entity is transferred to the main thread’s context. However, there is a problem because -[NSManagedObject didChangeValueForKey:]
gets called for every attribute that is transferred from the localContext
(background thread) to the main context (on the main thread). dirty
gets set with [NSDate date]
for each entity. Most of the time, dirty
does not get set last, which means when another attribute is set, dirty
is overwritten.
Is there a way to make sure dirty
is the last attribute that is set when transferring the NSManagedObject instance to the main thread’s context? I’m even willing to set dirty
when the object is saved (instead of when the properties are set).
I’ve tried all sorts of options, including checking against -[NSManagedObject isInserted]
and -[NSManagedObject isUpdated]
inside -[NSManagedObject didChangeValueForKey:]
. One other thing that is kind of annoying is that the new object is inserted before the attributes are transferred over (I thought I could have some sort of flag to lock/unlock setting dirty
).
Another thing to note is [NSManagedObject(_NSInternalMethods) _updateFromRefreshSnapshot:includingTransients:]
is what gets called right before -[NSManagedObject didChangeValueForKey:]
is called on the new object.
Any ideas? I’ve been facepalming over this for a couple days now.