iOS 通訊錄備份、恢復

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


                                                                                                                 













發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章