2012-04-10 14 views
9

tengo un problema extraño donde puedo registrar el iOS aplicación para escuchar a los cambios en el libro de direcciones móviles. Se llama al método correcto cuando algo cambia en la libreta de direcciones, pero se llama 2 - 6 veces.ABAddressBookRegisterExternalChangeCallback llama varias veces

Cuando el objeto se crea (Singleton, por lo que sólo un objeto), registro de notificaciones 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]; 
} 

Cualquier ideas de cómo resolver esto?

+2

También tengo este problema. Cada vez que cambio a la libreta de direcciones de iOS para cambiar el nombre de un contacto y volver a mi aplicación, la devolución de llamada se llama cuatro veces, siempre. Intenté agregar un contexto cuando me registré y veo que mi contexto se me envió en las cuatro llamadas. leí aquí: http://stackoverflow.com/questions/7116956/gcd-and-callbacks-concurrency-issue que alguien afirma que esto es un error conocido, pero no he encontrado. ¿Alguien tiene más información sobre este comportamiento irritante? –

Respuesta

1

tuve el mismo problema hace un tiempo, y tuve que resolverlo mediante la creación de un NSTimer para manejar las devoluciones de llamada duplicados:

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

Creo que está llamando al método: ABAddressBookRegisterExternalChangeCallback varias veces. –

+0

Disculpe, @Z S, me di cuenta de que estaba equivocado al respecto, tiene razón, lo siento por haber votado esta respuesta. – flypig

+0

Solo una pequeña mejora, el código ZS ejecutará el controlador solo después de que el temporizador caduque, puede verificar si changeTimer es nulo, si se trata de una notificación de manejo e iniciar el temporizador. El temporizador debe llamar a un selector que establece changeTimer = nil, entonces manejaremos la siguiente notificación después de que expire el tiempo de espera – marmor

0

tuve un problema similar. La devolución de llamada solo se llamaría una vez la primera vez, pero si salía y realizaba cambios en la libreta de direcciones por segunda vez, se llamaría varias veces. Para mí, el problema era el método que se celebró el ABAddressBookRegisterExternalChangeCallback estaba siendo llamado en el método de la AppDelegate applicationWillResignActive:.

La forma en que estaba utilizando la libreta de direcciones era para una configuración de sincronización. El problema era que estaba registrando la devolución de llamada externa cada vez que la configuración de sincronización estaban siendo salvados , en lugar de sólo cuando la configuración de sincronización estaban siendo cambiado .

Para ilustrar, aquí está el código que estaba llamando en el AppDelegate

- (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); 
    } 
} 

Quité la llamada a setAddressBookChanged en el método saveSettings, y sólo tenía que llama cuando se estaba creando la libreta de direcciones (primera serie de tiempo arriba) y cada vez que el usuario cambió la configuración de sincronización.

Espero que esto te ayude.

0

Mi solución fue bastante simple y funciona, no solo para esto sino para todas las devoluciones de llamada repetidas (incluidas las notificaciones locales llamadas repetidas): Guardo una propiedad con la última hora de la llamada y verifico el intervalo de tiempo. Espero que ayude, para mí hizo el trabajo.

AppDelegate * delegado = (__bridge AppDelegate *) contexto;

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]; 
    } 
} 
+0

buena lógica, pero ¿esto funciona o no en el caso de la sincronización de contactos múltiples en el fondo de Google? –

3

probar esto:

void addressBookChanged(ABAddressBookRef ab, CFDictionaryRef info, void *context){ 
ABAddressBookRevert(ab); 

    NSLog(@"ADDRESSBOOK CHANGED"); 
    [phoneBookCopy updateCopy]; 
    CFRelease(ab); 
} 

fue ayudado por mí.

Cuestiones relacionadas