我有一个奇怪的问题,我注册我的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];
}
任何想法如何解决这个问题?
答案 0 :(得分:3)
试试这个:
void addressBookChanged(ABAddressBookRef ab, CFDictionaryRef info, void *context){
ABAddressBookRevert(ab);
NSLog(@"ADDRESSBOOK CHANGED");
[phoneBookCopy updateCopy];
CFRelease(ab);
}
这对我有帮助。
答案 1 :(得分:1)
前一段时间我遇到了同样的问题,我必须通过创建NSTimer来解决它,以处理重复的回调:
[self.changeTimer invalidate];
self.changeTimer = nil;
self.changeTimer = [NSTimer scheduledTimerWithTimeInterval:3.0
target:self
selector:@selector(handleAdressBookExternalCallbackBackground)
userInfo:nil
repeats:NO];
答案 2 :(得分:0)
我有类似的问题。回调只会在第一次调用时调用,但是如果我第二次调出并更改了地址簿,那么它将被多次调用。
对我来说,问题是在appDelegate' ABAddressBookRegisterExternalChangeCallback
方法中调用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);
}
}
我在setAddressBookChanged
方法中移除了对saveSettings
的调用,只是在创建地址簿时(第一次设置)以及用户更改同步设置时调用了它。
希望这可以帮到你。
答案 3 :(得分:0)
我的解决方案很简单,它不仅适用于此,而且适用于所有重复的回调(包括本地通知重复调用): 我保留一个属性与最后的通话时间,并检查时间间隔。 希望它有所帮助,对我而言,它完成了这项工作。
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];
}
}