Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

KVO addObserver to CoreData object's one-to-many relationship

Hi everyone years reading StackOverflow, now I decided to join. I am struggling to get this resolved:

I have a "Depot" entity that has two to-many relationships "Persons" and "Trucks". I want to observe when, given a "Depot" object, there are changes (insert,remove) in one of the relationships (and understand in which one).

Currently i am doing this:

[mydepot addObserver:self forKeyPath:@"Trucks" options:NSKeyValueObservingOptionNew context:nil];

and

[mydepot addObserver:self forKeyPath:@"Persons" options:NSKeyValueObservingOptionNew context:nil];

but everytime something changes in one of the two related collections, observeValueForKeyPath gets called twice (one time for each keypath).

Am i doing it wrong? Looking at "change" dict, (observing with also OptionOld) shows no unexpected changes (when i change persons, trucks is not changed) but the notification is still raised.

Thanks, Pietro

edit: it seems that both times the "change" dict contains the entire relationship in the "new" field. (obviously one time Persons and one time Trucks)

edit2:as it happens even bserving simple properties, could it be related to the managedctx save operation? as if when you save, the entire object is considered changed..

like image 695
Peterdeka Avatar asked Mar 27 '13 12:03

Peterdeka


3 Answers

In the Key Value Observing Programming Guide it says that

If you're using Core Data, you can register the parent with the application's notification center as an observer of its managed object context. The parent should respond to relevant change notifications posted by the children in a manner similar to that for key-value observing.

That could effectively mean that the recommended practice is not to use addObserver:forKeyPath:options:context:, but register for the NSManagedObjectContextDidSaveNotification instead.

like image 125
Mundi Avatar answered Nov 02 '22 23:11

Mundi


If you set trucks atomically (something.trucks = newArray) you will get a value set notification. Instead use addObject/removeObject on the mutable array returned by [ something mutableArrayValueForKey:@"trucks" ].

You can also use/implement the KVO generated accessors insertObjectIntoTrucks: / countOfTrucks etc.

You should read the KVO documentation. Under "Indexed To-Many Relationship Compliance" and "Unordered To-Many Relationship Compliance" here.

like image 29
nielsbot Avatar answered Nov 03 '22 01:11

nielsbot


I come with the same problem. And I'm still sticking in this problem.

But what I'm sure is that the reason of the first time it be called is you do something like [Depot addPerson:person] while the reason of the second time it be called is the MOC save action will post a NSManagedObjectContextDidSaveNotification notification which let your observer think another modify just happen.

And what is worse in my problem is that because of the observer, I will lost some my modifications of core data.

This make me feel I'm so stupid for almost two days.

I'm thinking to use register NSManagedObjectContextDidSaveNotification in @Mundi 's answer

And if anyone have a better way , please let me know ASAP

like image 32
Puttin Avatar answered Nov 03 '22 01:11

Puttin