iOS 通讯录备份、恢复
2016-01-11 11:32
501 查看
和相册 备份一样,公司产品备份功能有通讯录备份 功能,自然也有通讯录恢复了。iOS通讯录相关操作,iOS对通讯录的操作离不开的框架:
说道通讯录的使用,我们还是先来说权限的问题,iOS7之前这些是不需要申请用户权限的,但是iOS7之后,苹果开始注重用户的隐私。如:相册,通讯录,地理位置等信息都是需要得到用户的许可的。
首先要申请用户权限。
但是要注意的是,即使获得了权限,用户还可以在设置中把咱们的权限关掉。所以每次对AddressBook的操作前要检查下权限是否正常。
接下来 获得所有的通讯录数据
由于我们公司的通讯录模块为初期版本,服务端设计的是通用模式(iOS Android通用),所以在号码读取和邮箱方面,做的差强人意,号码服务端限制死了四个号码字段,邮箱只有一个。值得一提的是,Addressbook给我们提供的是两个数组,一个是号码数组,一个是标签数组。但是都是c数组,我们要转换。我上面的代码没有要相关的标签,因为服务端规定死了四个。
接下来就是恢复通讯录:(两种模式)
1、删除本地所有,覆盖掉
第二种,合并联系人。由于json的代码结构不同,导致每个merge的比对算法不同。我们的比较死板。后期会改进。
如果有相同联系人。那就upadte 如果没有就Add。
大概就这些。一个AddressBookSyncManager就差不多了。
#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就差不多了。
相关文章推荐
- iOS 证书的那些坑
- iOS音频播放(ios自学笔记)
- IOS实现输入验证码、密码按位分割(二)
- ios开发——日常之dyld: Library not loaded: @rpath/MySDK.framework/MySDK 错误解决
- iOS标准时间与时间戳相互转换
- iOS 开发中在导航栏添加多个按钮并改变它的位置
- IOS实现自定义布局瀑布流
- iOS 真机测试提示"The identity used to sign the executable is no longer valid."
- iOS调用系统相册、相机 不能显示中文-解决方法
- iOS 自带定位服务
- iOS自定义Tabbar
- IOS学习笔记之网格视图
- iOS性能优化之内存管理:Analyze、Leaks、Allocations的使用和案例代码
- 分享一下我封装iOS自定义控件的体会,附上三个好用的控件Demo &lt;时间选择器&amp;多行输入框&amp;日期选择器&gt;
- iOS中PCH文件的配置
- iOS多线程的初步研究(十)-- dispatch同步
- iOS个人开发Tips
- iOS多线程的初步研究(九)— dispatch源
- iOS多线程的初步研究(八)-- dispatch队列
- iOS block的使用