I have a question regarding core data and notifications. After reading Apple docs, I didn’t find the answer.
This is the problem:
I have a managed object with a one-to-many relationship.
I would like to know when an object has been added or removed from this relationship.
(A “Category” has many “Items”)
I use this to know when item’s category are added or removed:
[category addObserver:self forKeyPath:@"items"
options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew
context:nil];
And then this method is called:
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
The problem:
Let’s say a category has 2 items, and I delete one of them. Now the category has only 1 item.
However, if I launch a fetched request from observeValueForKeyPath, it says the category has 2 items, but that is wrong, because it has now 1.
I guess this is because observeValueForKeyPath is called while context is being saved, [context save:&error] (that’s the only thing about this I found in Apple docs), and perhaps the modifications are not effective until [context save:&error] line is ended.
So, to test my theory, I modify my observeValueForKeyPath code, and I moved all code there inside a method, and I used:
[self performSelector:@selector(launchFetchedRequest)
withObject:nil afterDelay:0];
in order to execute that method the next run loop, that is, after [context save:&error]. And voilá, everything works fine now.
So, if I want to launch a fetch request inside observeValueForKeyPath, do I have to launch it the next run loop? Is this a normal behavior? How do you do this usually?
I’d like to know your thoughts about this topic. Thanks in advance.
Ricardo,
Use the
objectparameter. It is yourcategorycollection. All you have to do is look at what’s in it, so you don’t really need to run a query and hit the managed object context.The problem here is that the notification event is fired as the collection changes (KVO) and uses another thread loop, and the main thread has not propagated the change into the managed object context yet. If you used the
objectparameter, it should be correct.