I have a callback handler registered that listens to changes in the iOS Address Book. Due to some strange reason (for which a bug has been filed), this callback can sometimes be called more than once when the app returns from the background. I want my callback handler to run it's logic only once, even in cases the callback is called multiple times. This is how I register the callback:
ABAddressBookRegisterExternalChangeCallback(address_book, adressBookChanged, self);
This is how I structured my callback handler to take advantage of GCD to handle this. Unfortunately, it's not working, and GCD doesn't prevent the internal logic to be called twice...
void adressBookChanged(ABAddressBookRef ab, CFDictionaryRef info, void
*context)
{
NSLog(@"** IN addressBookChanged callback!");
ABAddressBookUnregisterExternalChangeCallback (ab, adressBookChanged, context);
__block BOOL fireOnce = FALSE;
dispatch_queue_t queue;
queue = dispatch_queue_create("com.myapp.abcallback", NULL);
dispatch_async(queue, ^{
if (fireOnce == FALSE) {
fireOnce = TRUE;
dispatch_queue_t queueInternal;
queueInternal = dispatch_queue_create("com.myapp.abcallbackInternal", NULL);
dispatch_async (queueInternal, ^{
NSLog(@"do internal logic");
});
dispatch_release(queueInternal);
}
});
dispatch_release(queue);
}
I'm pretty sure this code works for receiving multiple notifications, so are callbacks different? Do they spawn different threads automatically, making the fireOnce value to be FALSE each time? How should I write this code to prevent multiple callbacks from calling the internal logic more than once? I suppose I could use locks and/or synchronized blocks to achieve this, but GCD seemed like a cleaner way to achieve this.