和相冊 備份一樣,公司產品備份功能有通訊錄備份 功能,自然也有通訊錄恢復了。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就差不多了。