NSManagedObject changed properties after save
Asked Answered
P

3

8

Is it possible to find out which properties were saved on a managed object after the save occurs? For example, I have someone listening for managed object context saves, (NSManagedObjectContextDidSaveNotification) and I want to know which properties on the objects were saved.

Paolapaolina answered 18/11, 2011 at 0:23 Comment(0)
H
8

The NSManagedObjectContextDidSaveNotification does contain all three bits of information you would need to sync with a server. Check the [notification userInfo] and you will find three sets inside: NSInsertedObjectsKey, NSUpdatedObjectsKey, and NSDeletedObjectsKey

If you want to know what properties on an entity have changed that would require that you track them yourself using KVO. I would recommend against this as the odds of that level of effort being worth it over just pushing the entire object up to a server are slim.

Update #2

On further poking around:

From the NSManagedObjectContextWillSaveNotification you could loop through each set and reference the changedValues method. You could keep a reference to that dictionary until after you receive the NSManagedObjectContextDidSaveNotification and then process the changes. Still sounds very heavy to me.

Update

What is your end goal?!?!

If you are trying to figure out what to push to a server then being at the attribute level is too low. You should be syncing at the entity level.

If you are just trying to keep some internal consistency inside of your application then you are thinking way, way too low level. This is a solved problem. Core Data solved it.

Healy answered 18/11, 2011 at 0:59 Comment(12)
I will know which objects have been updated, deleted, or inserted, but not which specific propertiesPaolapaolina
Correct. You will be able to determine which objects but Core Data does not expose which properties on an object have changed. Answer updated.Healy
What I'm actually interested in knowing is which properties have changedPaolapaolina
I think you'd have to either cache active objects for comparison to inserted/updated/deleted, or use keyValueObserving (which I haven't done yet, but I think this is the classic case for it).Barman
Correct @Barman as I mentioned in the update to my answer; you would need to implement KVO on each instance of each entity and keep track of the changes at that level. That is most likely a bad idea and not worth the effort.Healy
Perhaps what I can do is listen for the context will save notification and then check the changed values in the context. I might not need to read from the database at this pointPaolapaolina
@Paolapaolina answer updated with another idea. Still seems wasteful to me though.Healy
I agree. But I think I will go the route of checking the managed object context willSave notification. From there I know which values have changed and just make sure that I don't try and read them from the database since they won't be saved yetPaolapaolina
It worries me when you say "don't try and read them from the database". If you are treating Core Data as a database you are going to be disappointed. You should treat Core Data as an object graph.Healy
But when you try and access objects in that graph across threads/contexts you have to get them from the databasePaolapaolina
@Paolapaolina maybe. Core Data is an object graph that can persist to a database. It can also persist to a binary store, an in-memory store, a server, or pretty much anything else. As I mentioned in my latest update to the answer; I think you are going to deep and are wasting your time on implementation details that should be beneath your notice.Healy
The approach of observing the will-save notification, and using changedValues is the way to go, but there is a subtlety you need to be aware of: the values in changedValues may not be final. The final value committed to the store could in some cases beLibratory
C
1

Why don't you get them when they are about to be saved. Subscribe to NSManagedObjectContextWillSaveNotification and check insertedObjects, updatedObjects and deletedObjects of the NSManagedObjectContext.

Update:

Even easier, get the user info of the NSManagedObjectContextDidSaveNotification

From the documentation:

Typically, on thread A you register for the managed object context save notification, NSManagedObjectContextDidSaveNotification. When you receive the notification, its user info dictionary contains arrays with the managed objects that were inserted, deleted, and updated on thread B.

http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/coredata/Articles/cdConcurrency.html#//apple_ref/doc/uid/TP40003385-SW1

Cayman answered 18/11, 2011 at 0:35 Comment(2)
Because what if I need to do something that involves fetching from the database on another thread? The value won't have been persisted yetPaolapaolina
@ Marcus S. Zarra: I meant methods of the NSManagedObjectContex, not the user info of the NSManagedObjectContextWillSaveNotificationCayman
P
1

Here's the solution I settled with. I have one singleton class that is notified when a context saves. The NSManagedObjectContextWillSave notification tells me which things have changed so I store them in a dictionary with the key being the context that saved. Then when I get the NSManagedObjectContextDidSave notification, I check the dictionary for the associated context. Finally, I remove that entry from the dictionary. Does that seem reasonable?

Paolapaolina answered 20/11, 2011 at 21:42 Comment(1)
See my answer because your end goal determines the answer. I suspect you are thinking too hard about this.Healy

© 2022 - 2024 — McMap. All rights reserved.