ABAddressBookRegisterExternalChangeCallback llamado varias veces

Tengo un extraño problema donde logging mi aplicación iOS para escuchar los cambios en la libreta de teléfonos. El método correcto se invoca cuando algo cambia en la libreta de direcciones pero se llama de 2 a 6 veces.

Cuando el object se crea (singleton, por lo que solo un object), me logging para las notifications con este código:

ABAddressBookRegisterExternalChangeCallback(notificationAddressBook, addressBookChanged, (__bridge_retained void *)self); 

El método que se llama se ve así:

 void addressBookChanged(ABAddressBookRef ab, CFDictionaryRef info, void *context){ ABAddressBookRevert(ab); NSLog(@"ADDRESSBOOK CHANGED"); [phoneBookCopy updateCopy]; } 

¿Alguna idea de como resolver esto?

testing esto:

 void addressBookChanged(ABAddressBookRef ab, CFDictionaryRef info, void *context){ ABAddressBookRevert(ab); NSLog(@"ADDRESSBOOK CHANGED"); [phoneBookCopy updateCopy]; CFRelease(ab); } 

Fue ayudado para mí.

Tuve el mismo problema hace un time, y tuve que resolverlo creando un NSTimer para manejar las devoluciones duplicadas:

 [self.changeTimer invalidate]; self.changeTimer = nil; self.changeTimer = [NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(handleAdressBookExternalCallbackBackground) userInfo:nil repeats:NO]; 

Tuve un problema similar. La callback solo se llamaría una vez la primera vez, pero si salía y hacía cambios a la libreta de direcciones por segunda vez, se llamaría varias veces. Para mí, el problema era el método en el que se estaba llamando ABAddressBookRegisterExternalChangeCallback en el método applicationWillResignActive: appDelegate.

La forma en que estaba usando la libreta de direcciones era para una configuration de synchronization. El problema era que estaba registrando la callback externa cada vez que se guardaban las configuraciones de synchronization, en lugar de solo cuando se cambiaba la configuration de synchronization.

Para ilustrar, aquí está el código que estaba llamando en la aplicaciónDelegate

 - (void)saveSettings { NSUserDefaults *syncSettingsData = [NSUserDefaults standardUserDefaults]; [syncSettingsData setObject:[NSNumber numberWithBool:self.isSyncingiPadContacts] forKey:SYNC_IPAD_CONTACTS_TURNED_ON]; [self setAddressBookChanged]; [syncSettingsData synchronize]; } - (void)setAddressBookChanged { if (self.isSyncingiPadContacts) { ABAddressBookRegisterExternalChangeCallback(self.addressBook, addressBookChanged, (__bridge void *)self); } else { ABAddressBookUnregisterExternalChangeCallback(self.addressBook, addressBookChanged, (__bridge void *) self); } } 

setAddressBookChanged la llamada a setAddressBookChanged en el método saveSettings , y simplemente la llamé cuando se creaba la agenda (la primera vez que se configuraba) y cada vez que el usuario cambiaba la configuration de synchronization.

Espero que esto te ayude.

Mi solución fue bastante simple y funciona, no solo para esto, sino para todas las llamadas repetidas (incluidas las notifications locales llamadas repetidas): guardo una propiedad con la última hora de la llamada y controlo el intervalo de time. Espero que sea de ayuda, para mí hizo el trabajo.

AppDelegate * delegate = (__bridge AppDelegate *) context;

 if (delegate.lastCall==nil) { delegate.lastCall = [[NSDate alloc]init]; } else { NSTimeInterval interval = [[NSDate date] timeIntervalSinceDate:delegate.lastCall]; if (interval<20) { return; } else { delegate.lastCall = [[NSDate alloc]init]; } }