CNContactStoreDidChangeNotification is fired multi

2019-02-05 14:04发布

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?

3条回答
老娘就宠你
2楼-- · 2019-02-05 14:42

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).

查看更多
不美不萌又怎样
3楼-- · 2019-02-05 14:44

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.

查看更多
ゆ 、 Hurt°
4楼-- · 2019-02-05 14:45

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.

查看更多
登录 后发表回答