问题
I am able to observe the CNContactStoreDidChangeNotification
when the contact database is changed while the app is in background state. I am pretty sure that only one observer was added to NSNotificationCenter
.
The problem is NSNotificationCenter
posts MULTIPLE times (2, 3, 5, and even more times) even if I only add one new contact.
Where is the problem?
回答1:
Make certain you aren't adding the observer multiple times. This can happen without you realizing it if (for example) you call -addObserver
from -viewDidLoad
or -viewDidAppear
in your view controller (as these might get called more than once throughout the life of your application), or from any of the application state callbacks in your app delegate (-applicationDidBecomeActive
, -applicationWillResignActive
, -applicationDidEnterBackground
, -applicationWillEnterForeground
, etc).
Wrap the call to -addObserver
in a conditional that ensures it can only be called once (set a flag), and put NSLog statements around it so you can see in the debug console if you are getting there more than once. Search your code for other calls to -addObserver
that you might have forgotten about.
Call -removeObserver
before adding it, just to be sure (making sure to pass the same name and object as when you added it). Calling -removeObserver
on an observer that doesn't exist is okay. Note that this is more of a band-aid than a fix - your code should be smart enough to know whether or not you've already added it - but this might help you diagnose the problem).
I just wrote a quick minimal test program that adds an observer (once!) on CNContactStoreDidChangeNotification
and I only get the notification once when I add or change a contact. Write a similar test program for yourself and see if you get the same result. If your test program works correctly, then it is likely that your app is doing something you don't expect (and calling -addObserver
multiple times).
回答2:
I had the same problem, the number of times it fired varied between 2 & 3. The solution that worked for me was to set a semaphore variable, set in the handler and reset the semaphore when finished. Wrap the address book processing in an if statement on the semaphore to ignore further calls. addressBkSemphore is reset to false in buildFrendsAndContacts
- (void)addressBkChange:(NSNotification *)note
{
if (addressBkSemphore == false)
{
addressBkSemphore = TRUE;
[self buildFrendsAndContacts];
}
}
Hope it helps.
回答3:
You can start a one time execution timer or a dispatch after few seconds and cancel it in case there's a new contacts update within those seconds, thus ensuring that only the timer or dispatch_after triggered by the last update will actually execute (taking into account that all update calls come one after the other within under a sec. difference, as far as I tested)
And btw, I could reproduce the issue only when making change to contacts on the same device with my app. If I change the contacts on another device linked to the same apple account, there was only one update.
来源:https://stackoverflow.com/questions/34560581/cncontactstoredidchangenotification-is-fired-multiple-times