2012-04-10 25 views
9

私はiOS-appを登録して電話アドレス帳の変更を聞くのに奇妙な問題があります。正しいメソッドは、何かがアドレス帳で変わったときに呼び出されますが、2〜6回呼び出されます。ABAddressBookRegisterExternalChangeCallbackが複数回呼び出されました

オブジェクトは(シングルトンなので、1つのオブジェクトのみ)、私はこのコードの通知を登録するに作成される

:次のようになりますと呼ばれる

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

方法:

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

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

どれをどのようにこれを解決するアイデア?

+2

この問題もあります。連絡先の名前を変更して自分のアプリに戻すためにiOSのアドレス帳に切り替えるたびに、コールバックは常に4回呼び出されます。登録したときにコンテキストを追加しようとしましたが、4つの呼び出しのすべてでコンテキストが送信されることがわかりました。 私はここでこれを読んでいます:http://stackoverflow.com/questions/7116956/gcd-and-callbacks-concurrency-issue誰かがこれが既知のバグだと主張していますが、私はそれを見つけませんでした。誰かがこの刺激的な行動に関する情報を持っていますか? –

答えて

1

私はしばらく前に同じ問題を抱えていた、と私は重複したコールバックを処理するためにNSTimerを作成することによってそれを解決しなければならなかった:

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

私はメソッドを呼び出すと思います:ABAddressBookRegisterExternalChangeCallbackを複数回実行します。 –

+0

申し訳ありませんが、@ Z S、私はこれについて間違っていることがわかりました、あなたは正しい、この回答に投票して申し訳ありません! – flypig

+0

わずかな改良点として、ZSコードはタイマーの期限が切れた後にのみハンドラを実行し、changeTimerがnilであるかどうかを確認し、通知を処理してタイマーを開始することができます。タイマーはchangeTimer = nilを設定するセレクタを呼び出す必要があります。タイムアウト後に次の通知を処理します。 – marmor

0

私は同様の問題がありました。コールバックは最初に一度だけ呼び出されますが、外出してアドレス帳にもう一度変更を加えた場合は、複数回呼び出されます。 私にとって、問題は、ABAddressBookRegisterExternalChangeCallbackがappDelegateのapplicationWillResignActive:メソッドで呼び出されていたというメソッドでした。

私がアドレス帳を使用していた方法は、同期設定用でした。問題は、同期設定がに変更されたときだけでなく、に保存されるたびに、外部コールバックを登録していたことです。説明するために

、ここで私は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); 
    } 
} 

で呼んでいたコードがある私はsaveSettings方法でsetAddressBookChangedへの呼び出しを削除し、アドレス帳が作成されていたとき、ちょうどそれは、(初めてセットと呼ばれていましたユーザーが同期設定を変更したときはいつでも)。

うまくいけば、これが役に立ちます。

0

私のソリューションはこれだけでなく、すべての繰り返しコールバック(ローカル通知の繰り返し呼び出しを含む)で動作します: 私は最後の呼び出し時間でプロパティを保持し、時間間隔を確認します。 それは私にとってそれは仕事をしたことを願っています。

AppDelegate * delegate =(__bridge AppDelegate *)context;

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

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

それは私のために助けられた。

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

良いロジックですが、これはGoogleからバックグラウンドで複数の連絡先を同期する場合に有効ですか? –

3

が、これは試してみてください。

関連する問題