views:

603

answers:

1

I am using the NSManagedObjectContextObjectsDidChangeNotification notfication in my app, I already now how to use it. As I have used the below code to add the observer …

- (void) awakeFromNib {
NSNotificationCenter *nc;
nc = [NSNotificationCenter defaultCenter];

[nc addObserver:self
       selector:@selector(syncKVO:)
           name:NSManagedObjectContextObjectsDidChangeNotification
         object:nil];
}

- (void)syncKVO:(id)sender {
NSNotificationCenter *nc;
nc = [NSNotificationCenter defaultCenter];
[nc removeObserver:self
              name:NSManagedObjectContextObjectsDidChangeNotification
            object:nil];

// Do stuff.

[nc addObserver:self
       selector:@selector(syncKVO:)
           name:NSManagedObjectContextObjectsDidChangeNotification
         object:nil];

}

But I would like to check the userInfo dictionary to make sure the method actually has to be triggered, How would I do this?

+1  A: 

Looking at the documentation for NSManagedObject gives you an answer.

A notification has three instance methods one of which is the -userInfo method which returns the userInfo dictionary.

It looks like your syncKVO: method is incorrect; notification handlers should take the notification object as a parameter.

The documentation for the notification you are looking for shows the keys that are in this dictionary for this notification and you can use something like this to get what you might need:

- (void)syncKVO:(NSNotification *)notification {
    NSDictionary *userInfoDictionary = [notification userInfo];
    NSSet *deletedObjects = [userInfoDictionary objectForKey:NSDeletedObjectsKey];

    // do what you want with the deleted objects
}
Abizern
Thanks, would this code work to check if the NSSet has objects in it? http://gist.github.com/224185
Joshua
Personally, I'd check for `if([deletedObjects count]) {…}` This is false if the set is nil or if it's empty.
Abizern
I see, so is this right now. http://gist.github.com/224185
Joshua
Apart from the typos, it looks okay. But the harder part is what you do with the objects.
Abizern
At the moment I don't need to do anything with the deleted objects.
Joshua
There's still one more typo. Have a look at my fork of your gist.
Abizern
Thanks, All fixed now. :)
Joshua
Ok, Could you help me with one last thing? The reason for this question (as you may now) is to try to stop my infinite loop problem. I still have the problem even with all the code I've added, this time the loop starts as soon I start the sync. Here's all my code related to this … http://gist.github.com/225186. Why is it still happening? Any help is greatly appreciated. Thanks.
Joshua
That's a big chunk of code so I haven't read it all; just a few points 1) You've got two methods that do the same thing. 2)Your sync: method assigns a different selector for the observation from the awakeFromNib method. 3) I suspect you're still observing the name property of your managed objects and those changes are probably still triggering stuff.
Abizern
Ok, I separated it into 2 method as only one will receive the notification. I didn't notice that it assigns a different selector, I'll change that now, Thanks. I'm watching if any objects have been deleted or updated, which in this case is the name which would be updated. I thought I would have stopped the loop by removing the observer at the start of the sync: and syncKVO: method and then adding it again at the end. No?
Joshua
Yay! By fixing those selectors it stops the loop! However, It should at the end of the action/method delete the deleted object from iCal, however it did delete it from iCal but it came back again in the outline view, so I added some more code to delete it again from the outline view but it still comes back, Any idea why?
Joshua
Nope. I don't know what you've added or changed. But here's a clue; All you are doing is removing self from the list of observers of your particular notifications, It is still observing changes for you JGManagedObject objects.
Abizern
This was the code that I added http://snapplr.com/gycp, it was there before but the point is it doesn't stop the object re appearing. Here's a recording of the problem http://droplr.com/20A7U. Does this help? I never added the notification center as an observer for JGManagedObject, or does it do this automatically?
Joshua
So it's disappearing from the calendar store and appearing in your app? In that case have a look at what you are doing to sync the calendar store items back into your app.
Abizern
It was supposed to be deleted from the calender store and stayed deleted in my App. Am I getting the problem because I am adding the objects to my app before I delete them from the calender store?
Joshua
I don't know. You've got so much duplicated code that it's hard to read. You'll just have to step through this in the debugger and see what is happening.
Abizern
Ok, I'll step through it all in the debugger. Here's a new gist with the code that's duplicated, http://gist.github.com/226293.
Joshua
Yeah, uh, thanks. What I meant was that if you've got duplicated code you really should refactor it.
Abizern
How do you refactor it?
Joshua
In this case, rather than have copy and pasted code in different places, you collect it in a single function, and then call the function. Makes it easier to read your code, and makes it easier to change because if you modify something you only need to do it in one place.
Abizern
Thanks I'll have a go at doing that. I've been doing at bit of debugging and noticed that the deleted object re-appears at the end of the deleted objects if method, it looks like it may actually continue onto the next if method for some reason. I haven't finished debugging yet, so I'll keep trying to pin point the problem.
Joshua
Still no luck, i've tried debugging the whole method the object is re added at the end of the if method. Here's a recording of the problem … http://droplr.com/22Wes. Although it doesn't look like it gets deleted in the first place (because it doesn't disappear), when not debugging it looks like it disappears and reappears. Could this problem be because NSManagedObjectContextObjectsDidChangeNotification is called while the object is being deleted not once it has been deleted?
Joshua
Well, watching a video of you debugging doesn't help me to see what's going wrong.
Abizern
Well, I cant find the problem. May I ask when does `NSManagedObjectContextObjectsDidChangeNotification` get called?
Joshua
From the documentation, the notification is **Posted when values of properties of objects contained in a managed object context are changed.**
Abizern
So after it has changed not while they are changing?
Joshua
You didn't ask, but here're some tips anyway. **1** You don't have to put a breakpoint on every line, you can put one at the top of the function and then use the _stop over_ or _step into_ buttons. **2** It's not enough to use the debugger to just see what the flow of your code is, you should be checking the values of variables as well. In your case it might help if you watched the arrays you use to synchronise your app and the calendar. **3** Try to get sync working without watching notifications and then add that back in.
Abizern
Thanks for the tips, I have tried it without watching notifications and it works fine. So the problem is something to do with it being triggered by the notification.
Joshua
Any idea why this is?
Joshua
It would not work if the notification was triggered during the deletion. But is the notification triggered during deletion?
Joshua