2012-04-10 14 views
9

Ich habe ein merkwürdiges Problem, wo ich meine iOS-App registriere, um Änderungen im Telefonadressbuch zu hören. Die richtige Methode wird aufgerufen, wenn sich etwas im Adressbuch ändert, aber es wird 2 - 6 Mal aufgerufen.ABAddressBookRegisterExternalChangeCallback mehrmals aufgerufen

Wenn das Objekt erstellt wird (Singleton, so dass nur ein Objekt), melde ich mich für Benachrichtigungen mit diesem Code:

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

Die Methode, die wie folgt aussieht genannt wird:

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

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

Beliebig Ideen wie man das löst?

+2

Ich habe auch dieses Problem. Jedes Mal, wenn ich zum iOS-Adressbuch wechsle, um den Namen eines Kontakts zu ändern und zu meiner App zurückzukehren, wird der Rückruf viermal aufgerufen - immer. Ich habe versucht, einen Kontext hinzuzufügen, als ich mich registriert habe und ich sehe, dass mein Kontext in allen vier Anrufen an mich gesendet wird. Ich lese hier: http://stackoverflow.com/questions/7116956/gcd-and-callbacks-concurrency-issue, dass jemand behauptet, dass dies ein bekannter Fehler ist, aber ich habe es nicht gefunden. Hat jemand mehr Informationen über dieses irritierende Verhalten? –

Antwort

1

hatte ich das gleiche Problem vor einer Weile, und ich hatte es zu lösen, indem ein NSTimer Schaffung der doppelten Rückrufe zu handhaben:

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

Ich denke, dass Sie die Methode aufrufen: ABAddressBookRegisterExternalChangeCallback mehrmals. –

+0

Sorry, @Z S, ich habe festgestellt, dass ich mich geirrt habe, du hast Recht, Entschuldigung für unten abgestimmt auf diese Antwort !!!! – flypig

+0

Nur eine kleine Verbesserung, ZS-Code wird den Handler erst nach Ablauf des Timers ausführen, können Sie überprüfen, ob changeTimer Null ist, wenn es handle Benachrichtigung und starten Sie den Timer. Der Timer sollte einen Selektor aufrufen, der changeTimer = nil setzt, also behandeln wir die nächste Benachrichtigung, nachdem die Zeit abgelaufen ist – marmor

0

ich ein ähnliches Problem hatte. Der Callback würde nur einmal beim ersten Mal aufgerufen werden, aber wenn ich ein zweites Mal Änderungen am Adressbuch vornehmen würde, würde es mehrmals aufgerufen werden. Für mich war das Problem die Methode, die das ABAddressBookRegisterExternalChangeCallback hielt, wurde in der AppDelegate's Methode aufgerufen.

Die Art, wie ich das Adressbuch verwendet habe, war für eine Synchronisierungseinstellung. Das Problem war, ich registrierte den externen Rückruf jedes Mal, wenn die Synchronisierungseinstellungen gespeichert wurden, und nicht nur, wenn die Synchronisierungseinstellungen geändert wurden.

Zur Veranschaulichung, hier ist der Code, den ich in dem AppDelegate Aufruf

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

ich den Anruf zu setAddressBookChanged im saveSettings Verfahren entfernt, und hatte gerade angerufen es, wenn der Adressbuchs (zum ersten Mal Satz erstellt wurde up) und wenn der Benutzer die Synchronisierungseinstellungen geändert hat.

Hoffentlich hilft das Ihnen.

0

Meine Lösung war ziemlich einfach und es funktioniert, nicht nur für diese, sondern für alle wiederholten Callbacks (einschließlich der lokalen Benachrichtigungen wiederholte Anrufe): Ich behalte eine Eigenschaft mit der letzten Anrufzeit und überprüfen Sie das Zeitintervall. Hoffe es hilft, für mich hat es den Job gemacht.

AppDelegate * Delegate = (__bridge AppDelegate *) Kontext;

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

gute Logik, aber das funktioniert oder nicht im Falle von mehreren Kontaktsynchronisierung im Hintergrund von Google? –

3

versuchen Sie dies:

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

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

Es wurde mir geholfen.

Verwandte Themen