ABAddressBookRegisterExternalChangeCallback извикан няколко пъти

Имам странен проблем, когато регистрирам приложението си за iOS, за да слушам промените в адресната книга на телефона. Правилният метод се извиква, когато нещо се промени в адресната книга, но се извиква 2 - 6 пъти.

Когато обектът бъде създаден (единичен, така че само един обект), се регистрирам за известия с този код:

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

Извиканият метод изглежда така:

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

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

Някакви идеи как да се реши това?


person joakimb    schedule 10.04.2012    source източник
comment
И аз имам този проблем. Всеки път, когато превключвам към адресната книга на iOS, за да променя името на контакт и да се върна обратно към моето приложение, обратното повикване се извиква четири пъти - винаги. Опитах се да добавя контекст, когато се регистрирах и виждам, че моят контекст ми е изпратен и при четирите обаждания. Прочетох тук: stackoverflow.com/questions/7116956/ че някой твърди, че това е известен бъг, но аз не го намерих. Някой има ли повече информация за това дразнещо поведение?   -  person Ricky Helgesson    schedule 16.05.2012


Отговори (4)


Опитайте тази:

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

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

На мен ми помогна.

person rusBogun    schedule 03.06.2014

Имах същия проблем преди известно време и трябваше да го разреша, като създадох NSTimer за обработка на дублиращите се обратни извиквания:

[self.changeTimer invalidate];
self.changeTimer = nil;
self.changeTimer = [NSTimer scheduledTimerWithTimeInterval:3.0
                                                            target:self
                                                          selector:@selector(handleAdressBookExternalCallbackBackground)
                                                          userInfo:nil
                                                           repeats:NO];
person Z S    schedule 16.05.2012
comment
Мисля, че извиквате метода: ABAddressBookRegisterExternalChangeCallback няколко пъти. - person Zain Raza; 06.11.2012
comment
Съжалявам, @Z S , открих, че съм грешал за това, прав си, съжалявам, че гласувах против този отговор!!!! - person flypig; 21.11.2012
comment
Само малко подобрение, ZS кодът ще стартира манипулатора само след като таймерът изтече, можете да проверите дали changeTimer е нула, дали е известие за обработка и да стартирате таймера. Таймерът трябва да извика селектор, който задава changeTimer = нула, така че ще обработим следващото известие след изтичане на времето за изчакване - person marmor; 06.01.2013

Имах подобен проблем. Обратното извикване ще бъде извикано само веднъж първия път, но ако изляза и направя промени в адресната книга втори път, то ще бъде извикано няколко пъти. За мен проблемът беше методът, който съдържаше ABAddressBookRegisterExternalChangeCallback, беше извикан в метода applicationWillResignActive: на appDelegate.

Начинът, по който използвах адресната книга, беше за настройка за синхронизиране. Проблемът беше, че регистрирах външното обратно извикване всеки път, когато настройките за синхронизиране бяха запазени, а не само когато настройките за синхронизиране бяха променени.

За илюстрация, ето кода, който извиквах в 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);
    }
}

Премахнах извикването на setAddressBookChanged в метода saveSettings и просто го извиках, когато адресната книга се създаваше (настройка за първи път) и всеки път, когато потребителят промени настройките за синхронизиране.

Надяваме се, че това ви помага.

person plasmaTonic    schedule 22.10.2013

Моето решение беше доста просто и работи не само за това, но и за всички повтарящи се обратни извиквания (включително повтарящите се повиквания на локални известия): поддържам свойство с времето на последното повикване и проверявам интервала от време. Надявам се да помогне, за мен свърши работа.

AppDelegate* делегат = (__bridge AppDelegate*)контекст;

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];
    }
}
person Eran Katsav    schedule 17.11.2013
comment
добра логика, но това работи или не в случай на синхронизиране на множество контакти на заден план от google? - person Lalit Kumar; 29.07.2015