您的位置:首页 > 移动开发 > IOS开发

iOS 通讯录备份、恢复

2016-01-11 11:32 501 查看
和相册 备份一样,公司产品备份功能有通讯录备份 功能,自然也有通讯录恢复了。iOS通讯录相关操作,iOS对通讯录的操作离不开的框架:

#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
iOS提供给我们了通讯录的相关信息,也给我们提供了简单的通讯录的控制器、UI,但是可定制的部分较少,一般不用他的UI,我们就不多讲他提供的UI部分。(大概也就能改个颜色,组件 什么的,导航栏颜色等)。

说道通讯录的使用,我们还是先来说权限的问题,iOS7之前这些是不需要申请用户权限的,但是iOS7之后,苹果开始注重用户的隐私。如:相册,通讯录,地理位置等信息都是需要得到用户的许可的。

首先要申请用户权限。

- (void)viewDidLoad {
[super viewDidLoad];

self.view.backgroundColor=[UIColor colorWithRed:248.0/255.0 green:248.0/255.0 blue:248.0/255.0 alpha:1.0];
self.title=@"通讯录同步";
[self initView];
[self addRightBarItem];
CFErrorRef error=NULL;
//请求权限
ABAddressBookRef addressBook=ABAddressBookCreateWithOptions(NULL, &error);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
});
if (error==NULL) {
CFRelease(addressBook);
}

}
获得用户权限后,才能对AddressBook做相关操作。

但是要注意的是,即使获得了权限,用户还可以在设置中把咱们的权限关掉。所以每次对AddressBook的操作前要检查下权限是否正常。

//检测授权状态
+(BOOL)checkAuthorizationStatus{
if (ABAddressBookGetAuthorizationStatus()!=kABAuthorizationStatusAuthorized) {
return NO;
}else{
return YES;
}
}


接下来 获得所有的通讯录数据

-(NSMutableArray *)getLocationAllPeople{
[self.allPeople removeAllObjects];
if (![JYAddressBookSyncManager checkAuthorizationStatus]) {
return self.allPeople;
}else{

if (ABAddressBookGetAuthorizationStatus()!=kABAuthorizationStatusAuthorized) {
}else{
}
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
CFArrayRef results = ABAddressBookCopyArrayOfAllPeople(addressBook);
for (int i = 0; i<CFArrayGetCount(results); i++) {
ABRecordRef person = CFArrayGetValueAtIndex(results, i);
Person * people = [[Person alloc]init];
people.id = ABRecordGetRecordID(person);
people.first_name = CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));

people.last_name = CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNameProperty));

people.nick = CFBridgingRelease(ABRecordCopyValue(person, kABPersonNicknameProperty));

people.desc = CFBridgingRelease(ABRecordCopyValue(person, kABPersonNoteProperty));

people.org = CFBridgingRelease(ABRecordCopyValue(person, kABPersonOrganizationProperty));

people.birth =CFBridgingRelease(ABRecordCopyValue(person, kABPersonBirthdayProperty));

//取邮箱第一个。
ABMultiValueRef emailsProperty=ABRecordCopyValue(person, kABPersonEmailProperty);

NSArray *emailsArray=CFBridgingRelease(ABMultiValueCopyArrayOfAllValues(emailsProperty));
if(emailsArray.count>0){
NSString *email=[emailsArray objectAtIndex:0];
people.email = email;
}
CFRelease(emailsProperty);
//取电话号码
ABMultiValueRef phoneNumbersProperty = ABRecordCopyValue(person, kABPersonPhoneProperty);
NSArray * phoneNumberArray = CFBridgingRelease(ABMultiValueCopyArrayOfAllValues(phoneNumbersProperty));
for (int j =  0; j<phoneNumberArray.count; j++) {
NSString *phoneNumber=[phoneNumberArray objectAtIndex:j];
//            NSString *phoneNumberLabel=CFBridgingRelease(ABMultiValueCopyLabelAtIndex(phoneNumbersProperty, j));
if(j == 0){
people.tel = phoneNumber;
}else if (j == 1){
people.mobile = phoneNumber;
}else if (j == 2){
people.home = phoneNumber;
}else if (j == 3){
people.office = phoneNumber;
}
}
CFRelease(phoneNumbersProperty);
//获取地址
//        ABMultiValueRef address = ABRecordCopyValue(person, kABPersonAddressProperty);
//        int count = (int)ABMultiValueGetCount(address);
//        if(count>0){
//            people.addr = CFBridgingRelease(ABMultiValueCopyValueAtIndex(address, 0));
//        }
[self.allPeople addObject:people];
CFRelease(person);
}
NSLog(@"本地读取数据:%@",self.allPeople);
CFRelease(addressBook);

return self.allPeople;
}

}


由于我们公司的通讯录模块为初期版本,服务端设计的是通用模式(iOS Android通用),所以在号码读取和邮箱方面,做的差强人意,号码服务端限制死了四个号码字段,邮箱只有一个。值得一提的是,Addressbook给我们提供的是两个数组,一个是号码数组,一个是标签数组。但是都是c数组,我们要转换。我上面的代码没有要相关的标签,因为服务端规定死了四个。

接下来就是恢复通讯录:(两种模式)

1、删除本地所有,覆盖掉

//恢复 (删除本机)
-(void)resumeWithDeleteLocation:(AddressPeople*)people andComplete:(deleteSuccessBlock)block{
if (![JYAddressBookSyncManager checkAuthorizationStatus]) {

}else{
[self getNetworkAllPeopleWithPeople:people andComplete:^(NSMutableArray *netData) {
//获得所有用户
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
CFArrayRef results = ABAddressBookCopyArrayOfAllPeople(addressBook);
for (id peo in (__bridge NSArray *)results) {
ABRecordRef oldPeople = (__bridge ABRecordRef)(peo);
if (!oldPeople) {
break;
}
CFErrorRef error = NULL;
ABAddressBookRemoveRecord(addressBook, oldPeople, &error);
CFRelease(oldPeople);
}
ABAddressBookSave(addressBook, &error);
CFRelease(addressBook);
for (Person * person in netData) {
if(person.tel.length>0||person.mobile.length>0||person.office.length>0||person.home.length>0){
[self addLocalPersonWithNetPerson:person];
}
}
[SXLoadingView showAlertHUD:@"恢复成功" duration:0.5];
block(people);
}];
}

}
逐条添加

//
-(void)addLocalPersonWithNetPerson:(Person *)per{
ABAddressBookRef addressBook = ABAddressBookCreate();
ABRecordRef person = ABPersonCreate();
// 电话号码数组
NSMutableArray * phones = [NSMutableArray array];
NSMutableArray * labels = [NSMutableArray array];
if(per.tel.length>0){
[phones addObject:per.tel];
[labels addObject:@"住宅"];
}
if(per.home.length>0){
[phones addObject:per.home];
[labels addObject:@"家庭"];
}
if(per.mobile.length>0){
[phones addObject:per.mobile];
[labels addObject:@"手机"];
}
if(per.office.length>0){
[phones addObject:per.office];
[labels addObject:@"工作"];
}

if(per.first_name.length>0||per.last_name.length>0){
ABRecordSetValue(person, kABPersonFirstNameProperty, (__bridge CFStringRef)per.first_name, NULL);
ABRecordSetValue(person, kABPersonLastNameProperty, (__bridge CFStringRef) per.last_name, NULL);
}
else{
ABRecordSetValue(person, kABPersonFirstNameProperty, (__bridge CFTypeRef)(per.name), NULL);
}
// 设置birthday属性
//ABRecordSetValue(person, kABPersonBirthdayProperty, (__bridge CFDateRef)per.birth, NULL);
ABMultiValueRef mv = ABMultiValueCreateMutable(kABMultiStringPropertyType);
// 添加电话号码与其对应的名称内容
for (int i = 0; i < [phones count]; i ++) {
ABMultiValueIdentifier mi = ABMultiValueAddValueAndLabel(mv, (__bridge CFStringRef)[phones objectAtIndex:i], (__bridge CFStringRef)[labels objectAtIndex:i], &mi);
}

ABRecordSetValue(person, kABPersonPhoneProperty, mv, NULL);
if (mv) {
CFRelease(mv);
}
ABAddressBookAddRecord(addressBook, person, NULL);
ABAddressBookSave(addressBook, NULL);
if (addressBook) {
CFRelease(addressBook);
}
}


第二种,合并联系人。由于json的代码结构不同,导致每个merge的比对算法不同。我们的比较死板。后期会改进。

#pragma mark - 合并联系人
-(void)mergeAddressBookWithLocalAndNet:(AddressPeople *)people andComplete:(mergeSeccessBlock)block{
[self getNetworkAllPeopleWithPeople:people andComplete:^(NSMutableArray *netData) {
NSMutableArray *localPersons = [self getLocationAllPeople];
for (Person * person in netData) {
BOOL isHave = NO;
for (Person * localPerson in localPersons) {
isHave = [self isSamePeopleByPeople:person OtherPeople:localPerson];
if (isHave) {
break;
}
}
if(isHave){
[self updateLocalPersonWithNetPerson:person];
}
else{
[self addLocalPersonWithNetPerson:person];
}
}
block();
}];
}

-(BOOL)isSamePeopleByPeople:(Person*)person OtherPeople:(Person*)otherPerson{
//安卓端只有name属性
NSMutableArray * phoneNumArr = [NSMutableArray array];
if(otherPerson.tel){
[phoneNumArr addObject:otherPerson.tel];
}
if (otherPerson.home) {
[phoneNumArr addObject:otherPerson.home];
}
if (otherPerson.office) {
[phoneNumArr addObject:otherPerson.office];
}
if (otherPerson.mobile) {
[phoneNumArr addObject:person.mobile];
}
//    NSLog(@"personName:%@  first:%@ last:%@ - otherPersonName:%@ %@",person.name,person.first_name,person.last_name, otherPerson.first_name,otherPerson.last_name);
if(!IsNilString(person.name)){
if ([person.name isEqualToString:otherPerson.first_name]||[person.name isEqualToString:[NSString stringWithFormat:@"%@ %@",otherPerson.first_name,otherPerson.last_name]]) {
if ([phoneNumArr indexOfObject:person.tel] != NSNotFound) {
return YES;
}
}
}
else if ([person.first_name isEqualToString:otherPerson.first_name]&&([person.last_name isEqualToString:otherPerson.last_name]||IsNilString(person.last_name)==IsNilString(otherPerson.last_name))) {
if ([phoneNumArr indexOfObject:person.tel] != NSNotFound) {
return YES;
}
}
return NO;
}


如果有相同联系人。那就upadte 如果没有就Add。

-(void)updateLocalPersonWithNetPerson:(Person *)person{
Person *peopleOfLocation;
if (self.allPeople.count!=0) {
for (Person * p in self.allPeople) {
if (p.id==person.id) {
peopleOfLocation=p;
break;
}
}
CFErrorRef error=NULL;
ABAddressBookRef addressBook=ABAddressBookCreateWithOptions(NULL, &error);
ABRecordRef person1=ABAddressBookGetPersonWithRecordID(addressBook, peopleOfLocation.id);
//修改单值属性
if (IsNilString(peopleOfLocation.nick)) {
ABRecordSetValue(person1, kABPersonNicknameProperty, (__bridge CFTypeRef)person.nick, &error);
}
if (IsNilString(peopleOfLocation.desc)) {
ABRecordSetValue(person1, kABPersonNoteProperty, (__bridge CFTypeRef)person.desc, &error);
}
if (IsNilString(peopleOfLocation.org)) {
ABRecordSetValue(person1, kABPersonOrganizationProperty, (__bridge CFTypeRef)person.org, &error);
}
if (!peopleOfLocation.birth) {
ABRecordSetValue(person1, kABPersonBirthdayProperty, (__bridge CFTypeRef)person.birth, &error);
}
//修改多值属性
//电话号码
ABMutableMultiValueRef multi=ABMultiValueCreateMutable(kABMultiStringPropertyType);
NSArray * phoneNumberArray = CFBridgingRelease(ABMultiValueCopyArrayOfAllValues(multi));
if(person.home){
if([phoneNumberArray indexOfObject:person.home] == NSNotFound){
ABMultiValueIdentifier mi = ABMultiValueAddValueAndLabel(multi, (__bridge CFStringRef)person.home, (__bridge CFStringRef)@"家庭", &mi);
}
}
if(person.office){
if([phoneNumberArray indexOfObject:person.office] == NSNotFound){
ABMultiValueIdentifier mi = ABMultiValueAddValueAndLabel(multi, (__bridge CFStringRef)person.office, (__bridge CFStringRef)@"工作", &mi);
}
}
if (person.mobile) {
if([phoneNumberArray indexOfObject:person.mobile] == NSNotFound){
ABMultiValueIdentifier mi = ABMultiValueAddValueAndLabel(multi, (__bridge CFStringRef)person.mobile, (__bridge CFStringRef)@"手机", &mi);
}
}

ABRecordSetValue(person1, kABPersonPhoneProperty, multi, &error);
CFRelease(multi);

//添加记录到数据库
ABAddressBookAddRecord(addressBook, person1, &error);
//保存到数据库
ABAddressBookSave(addressBook, &error);
//        CFRelease(person);
CFRelease(addressBook);
}

}


大概就这些。一个AddressBookSyncManager就差不多了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: