Man*_*ani 5 objective-c addressbook abaddressbook ios abaddressbooksource
关于收听iOS地址簿更改回调,提出了许多SO问题.着名问题地址簿同步.
但我的问题很窄,即如何在地址簿同步回调期间删除哪些联系人被删除.
void MyAddressBookExternalChangeCallback (ABAddressBookRef ntificationaddressbook,CFDictionaryRef info,void *context)
{
NSLog(@"Changed Detected......");
/*
NSDate *lastSyncTime = [self gettingLastSyncTime];
// By above time, I could get which contacts are modified(kABPersonModificationDateProperty)
// and which contacts are created newly( ABRecordGetRecordID()
// But how can I get this contact was DELETED?
*/
}
Run Code Online (Sandbox Code Playgroud)
但有人在清理这个问题检测什么改变.......在这里,他们做了(a)第一次存储所有记录ID(b)在同步期间,检查所有存储的记录ID与当前地址簿ID,以检查它们是否可用.如果没有,则假设它被删除联系(昂贵的操作).
我的问题:还有其他方法来检测DELETED联系人吗?
小智 1
据我所知,唯一的方法是以某种方式存储联系人 ID 并检查修改,因为MyAddressBookExternalChangeCallback只有当您的应用程序处于活动状态或在后台时才会调用原因,因此当您的应用程序终止时,您将无法跟踪那些变化。这是我的地址簿同步控制器的实现,它只是保持您与设备的本地联系人的最新状态:
// Header.h
@interface AddressBookSyncController : NSObject
+ (instancetype)sharedInstance;
+ (NSString *)archiveFilePath;
- (void)syncAddressBook;
- (void)beginObserving;
- (void)invalidateObserving;
@end
// Implementation.m
NSString *const AddressBookSyncAllKey = @"AddressBookSyncAllKey";
@interface AddressBookSyncController ()
@property (nonatomic) ABAddressBookRef addressBook;
@property (nonatomic) BOOL isObserving;
@end
@implementation AddressBookSyncController
+ (instancetype)sharedInstance
{
static AddressBookSyncController *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [AddressBookSyncController new];
});
return instance;
}
+ (NSString *)archiveFilePath
{
// Your archive file path...
}
- (void)syncAddressBook
{
dispatch_async(dispatch_get_main_queue(), ^{
if (ABAddressBookGetAuthorizationStatus() != kABAuthorizationStatusAuthorized) return;
NSString *archiveFilePath = [AddressBookSyncController archiveFilePath];
BOOL needSyncAllContacts = [[[NSUserDefaults standardUserDefaults] objectForKey:AddressBookSyncAllKey] boolValue];
BOOL archiveExists = [[NSFileManager defaultManager] fileExistsAtPath:archiveFilePath];
if (!needSyncAllContacts && !archiveExists) return;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, nil);
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
NSInteger nPeople = ABAddressBookGetPersonCount(addressBook);
NSMutableArray *syncContacts = [NSMutableArray arrayWithCapacity:nPeople];
NSMutableArray *archivedContacts = archiveExists ? [[NSKeyedUnarchiver unarchiveObjectWithFile:archiveFilePath] mutableCopy] : [NSMutableArray array];
if (needSyncAllContacts)
{
NSMutableArray *newContacts = [NSMutableArray array];
for (NSInteger i = 0; i < nPeople; ++i)
{
ABRecordRef record = CFArrayGetValueAtIndex(allPeople, i);
NSInteger recordId = ABRecordGetRecordID(record);
NSDate *modificationDate = (__bridge_transfer NSDate *)ABRecordCopyValue(record, kABPersonModificationDateProperty);
AddressContact *contact = [[archivedContacts filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"recordId == %i", recordId]] firstObject];
if (contact && [contact.modificationDate isEqualToDate:modificationDate]) continue;
AddressContact *newContact = [AddressContact addressContactWithRecord:record];
[syncContacts addObject:newContact];
if (contact)
{
NSUInteger idx = [archivedContacts indexOfObject:contact];
if (idx != NSNotFound)
{
[archivedContacts replaceObjectAtIndex:idx withObject:newContact];
}
else
{
NSLog(nil, @"idx == NSNotFound for syncAddressBook");
}
}
else
{
[newContacts addObject:newContact];
}
}
[archivedContacts addObjectsFromArray:newContacts];
}
else
{
for (NSInteger i = 0, l = archivedContacts.count; i < l; ++i)
{
AddressContact *contact = [archivedContacts objectAtIndex:i];
ABRecordRef record = ABAddressBookGetPersonWithRecordID(addressBook, (int)contact.recordId);
if (!record) continue;
NSDate *modificationDate = (__bridge_transfer NSDate *)ABRecordCopyValue(record, kABPersonModificationDateProperty);
if ([modificationDate isEqualToDate:contact.modificationDate]) continue;
AddressContact *newContact = [AddressContact addressContactWithRecord:record];
[syncContacts addObject:newContact];
[archivedContacts replaceObjectAtIndex:i withObject:newContact];
}
}
CFRelease(allPeople);
CFRelease(addressBook);
BOOL result = NO;
if ([syncContacts count] != 0)
{
// Do your logic with contacts
result = [NSKeyedArchiver archiveRootObject:archivedContacts toFile:archiveFilePath];
}
NSLog(@"Archiving %@", result ? @"Succeed" : @"Failed");
[[NSUserDefaults standardUserDefaults] setObject:@(NO) forKey:AddressBookSyncAllKey];
[[NSUserDefaults standardUserDefaults] synchronize];
});
}
- (void)beginObserving
{
if (self.isObserving || ABAddressBookGetAuthorizationStatus() != kABAuthorizationStatusAuthorized) return;
self.addressBook = ABAddressBookCreateWithOptions(NULL, nil);
ABAddressBookRegisterExternalChangeCallback(self.addressBook, addressBookChanged, (__bridge void *)self);
self.isObserving = YES;
}
- (void)invalidateObserving
{
if (!self.isObserving) return;
ABAddressBookUnregisterExternalChangeCallback(self.addressBook, addressBookChanged, (__bridge void *)self);
CFRelease(self.addressBook);
self.isObserving = NO;
}
void addressBookChanged(ABAddressBookRef reference, CFDictionaryRef dictionary, void *context)
{
NSLog(@"%@ changed %@", reference, dictionary);
ABAddressBookRevert(reference);
[(__bridge AddressBookSyncController *)context syncAddressBook];
}
@end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
549 次 |
| 最近记录: |