iOS通訊錄整合,相容iOS789寫法,附demo,iosios789

來源:互聯網
上載者:User

iOS通訊錄整合,相容iOS789寫法,附demo,iosios789

蘋果的通訊錄功能在iOS7,iOS8,iOS9 都有著一定的不同,iOS7和8用的是 <AddressBookUI/AddressBookUI.h> ,但是兩個系統版本的代理方法有一些變化,有些代理方法都標註了 NS_DEPRECATED_IOS(2_0, 8_0) 並推薦了另一個代理方法與之對應。  而iOS8到iOS9則是直接棄用了<AddressBookUI/AddressBookUI.h>取而代之的是<ContactsUI/ContactsUI.h>,後者是OC調用,據說當時蘋果宣布棄用AddressBookUI還引來了陣陣歡呼。這也就是在使用通訊錄功能時得考慮版本各種判斷,我也就是工作中遇到了這種坑,然後就順手相容封裝了一下。希望能解決這個問題。

 

我覺得通訊錄這裡的類結構沒必要像SDWebImage或是Core Location這樣列出來詳細去說。大家用到通訊錄無外乎就三個功能:

1.點擊彈出通訊錄頁面,選擇了一個連絡人的電話後直接將資訊填到頁面輸入框內。

2.遍曆所有的通訊錄資料統一做大量操作,搭建新頁面或直接上傳。

3.給通訊錄寫入一條資訊。

 

這裡會先對比一下iOS789的寫法,最後奉上demo(一個封裝後的庫,提供了非常便利的api)。不關心內部實現的朋友可以直接拉到demo部分。

 

一、首先是擷取通訊錄的許可權

iOS7和8保持一致

    ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();    ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);    if (status == kABAuthorizationStatusNotDetermined) {        NSLog(@"還沒問");        ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error){            if(granted){                NSLog(@"點擊同意");            }else{                NSLog(@"點擊拒絕");            }        });    }else if (status == kABAuthorizationStatusAuthorized){        NSLog(@"已經授權");        [self loadPerson];    }else {        NSLog(@"沒有授權");        // 彈窗提示去擷取許可權    }

iOS9及以後調用方法改成

     CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];    if (status == CNAuthorizationStatusNotDetermined) {        [[[CNContactStore alloc]init] requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {            NSLog(@"還沒問");            if(granted){                NSLog(@"點擊了同意");                [self loadPerson];            }else{                NSLog(@"點擊了拒絕");            }        }];    }else if (status == CNAuthorizationStatusAuthorized){         NSLog(@已經授權");    }else {        NSLog(@"沒有授權");    }    
  二、彈出通訊錄選擇介面

iOS7的寫法如下,代理方法的傳回值大多是BOOL類型。

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person{    return YES;}- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier{    ABMultiValueRef phone = ABRecordCopyValue(person, kABPersonPhoneProperty);    long index = ABMultiValueGetIndexForIdentifier(phone,identifier);    NSString *phoneNO = (__bridge NSString *)ABMultiValueCopyValueAtIndex(phone, index);        CFStringRef lastName = ABRecordCopyValue(person, kABPersonLastNameProperty);    CFStringRef firstName = ABRecordCopyValue(person, kABPersonFirstNameProperty);        NSString *lastname = (__bridge_transfer NSString *)(lastName);    NSString *firstname = (__bridge_transfer NSString *)(firstName);        if (phone) {        [peoplePicker dismissViewControllerAnimated:YES completion:nil];        return NO;    }    return YES;}

 

iOS8的代理方法換了,改成了下面兩個,但是方法內部的取值基本相同

// 點擊了通訊錄名字就會退出- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person;// 點擊了名字裡面的電話或郵箱才會退出- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier;

至於會調用哪一個方法,可以根據實際需要去選擇,在彈出介面的方法中predicateForSelectionOfPerson 這個屬性傳false就是調用下面的。

    ABPeoplePickerNavigationController *pickervc = [[ABPeoplePickerNavigationController alloc] init];    pickervc.predicateForSelectionOfPerson = [NSPredicate predicateWithValue:false];    pickervc.peoplePickerDelegate = self;    [target presentViewController:pickervc animated:YES completion:nil];

 

iOS9系統下的彈出選取器方法 和 代理方法如下

 // 彈出選取器  - (void)presentPageOnTarget{     CNContactPickerViewController *contactVc = [[CNContactPickerViewController     alloc] init];     contactVc.delegate = self;     [target presentViewController:contactVc animated:YES completion:nil];}// 代理方法- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContact:(CNContact *)contact{    SXPersonInfoEntity *personEntity = [SXPersonInfoEntity new];    NSString *lastname = contact.familyName;    NSString *firstname = contact.givenName;    NSLog(@"%@ %@", lastname, firstname);    personEntity.lastname = lastname;    personEntity.firstname = firstname;        NSMutableString *fullname = [[NSString stringWithFormat:@"%@%@",lastname,firstname] mutableCopy];    [fullname replaceOccurrencesOfString:@"(null)" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, fullname.length)];    personEntity.fullname = fullname;        NSString *fullPhoneStr = [NSString string];    NSArray *phoneNums = contact.phoneNumbers;    for (CNLabeledValue *labeledValue in phoneNums) {        NSString *phoneLabel = labeledValue.label;        CNPhoneNumber *phoneNumer = labeledValue.value;        NSString *phoneValue = phoneNumer.stringValue;        NSLog(@"%@ %@", phoneLabel, phoneValue);        if (phoneValue.length > 0) {            fullPhoneStr = [fullPhoneStr stringByAppendingString:phoneValue];            fullPhoneStr = [fullPhoneStr stringByAppendingString:@","];        }    }    if (fullPhoneStr.length > 1) {        personEntity.phoneNumber = [fullPhoneStr substringToIndex:fullPhoneStr.length - 1];    }    self.chooseAction(personEntity);}

這個是點擊了名字就直接回調的方法,如果希望點擊了屬性再回調,則需要加上這一行

contactVc.predicateForSelectionOfContact = [NSPredicate predicateWithValue:false];// 代理方法調用- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperty:(CNContactProperty *)contactProperty

 

三、擷取全部通訊錄資訊

關於批量擷取所有通訊錄資訊的方法有點冗長,這裡就不一一貼了,只貼下iOS9的寫法,iOS7和8的代碼demo裡都有。

- (void)printAllPerson{    // 擷取    CNContactStore *contactStore = [[CNContactStore alloc] init];    NSArray *keys = @[CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey];    CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:keys];        // 遍曆    [contactStore enumerateContactsWithFetchRequest:request error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {        NSString *lastname = contact.familyName;        NSString *firstname = contact.givenName;        NSLog(@"%@ %@", lastname, firstname);        NSArray *phoneNums = contact.phoneNumbers;        for (CNLabeledValue *labeledValue in phoneNums) {            NSString *phoneLabel = labeledValue.label;            CNPhoneNumber *phoneNumer = labeledValue.value;            NSString *phoneValue = phoneNumer.stringValue;            NSLog(@"%@ %@", phoneLabel, phoneValue);        }    }];}

 

四、寫入通訊錄

因為寫入的話這個功能有點重量級,寫入的時候要寫入,名字、電話、email、地址等等,這就會使得api過於複雜。暫時我見到過的做法大多都是如果使用者給了通訊錄許可權 那就給你插入一條名字+電話,我做了只有這兩個入參的api,當然使用時也完全可以擴充成更多參數的。

iOS7和8

- (void)creatItemWithName:(NSString *)name phone:(NSString *)phone{    if((name.length < 1)||(phone.length < 1)){        NSLog(@"輸入屬性不可為空");        return;    }    CFErrorRef error = NULL;        ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);    ABRecordRef newRecord = ABPersonCreate();    ABRecordSetValue(newRecord, kABPersonFirstNameProperty, (__bridge CFTypeRef)name, &error);        ABMutableMultiValueRef multi = ABMultiValueCreateMutable(kABMultiStringPropertyType);    ABMultiValueAddValueAndLabel(multi, (__bridge CFTypeRef)name, kABPersonPhoneMobileLabel, NULL);        ABRecordSetValue(newRecord, kABPersonPhoneProperty, multi, &error);    CFRelease(multi);        ABAddressBookAddRecord(addressBook, newRecord, &error);        ABAddressBookSave(addressBook, &error);    CFRelease(newRecord);    CFRelease(addressBook);}

iOS9下

- (void)creatItemWithName:(NSString *)name phone:(NSString *)phone{    // 建立對象    // 這個裡面可以添加多個電話,email,地址等等。 感覺使用率不高,只提供了最常用的屬性:姓名+電話,需要時可以自行擴充。    CNMutableContact * contact = [[CNMutableContact alloc]init];    contact.givenName = name?:@"defaultname";    CNLabeledValue *phoneNumber = [CNLabeledValue labeledValueWithLabel:CNLabelPhoneNumberMobile value:[CNPhoneNumber phoneNumberWithStringValue:phone?:@"10086"]];    contact.phoneNumbers = @[phoneNumber];        // 把對象加到請求中    CNSaveRequest * saveRequest = [[CNSaveRequest alloc]init];    [saveRequest addContact:contact toContainerWithIdentifier:nil];        // 執行請求    CNContactStore * store = [[CNContactStore alloc]init];    [store executeSaveRequest:saveRequest error:nil];}

 

五、我的demo

因為不同版本用的類和枚舉都不一樣,所以我要設定一個統一的,並且在我的manager中處理各個版本間的判斷。 最後開放出來統一的api,只要引入標頭檔SXAddressBookManager.h 就可以使用這些通用介面了。

①檢查目前狀態,有兩種api 

- (void)checkStatus1{    SXAddressBookAuthStatus status = [[SXAddressBookManager manager]getAuthStatus];    if (status == kSXAddressBookAuthStatusNotDetermined) {        [[SXAddressBookManager manager]askUserWithSuccess:^{            NSLog(@"點擊同意");        } failure:^{            NSLog(@"點擊拒絕");        }];    }else if (status == kSXAddressBookAuthStatusAuthorized){        NSLog(@"已有許可權");    }else{        NSLog(@"沒有許可權");    }}
- (void)checkStatus2{    [[SXAddressBookManager manager]checkStatusAndDoSomethingSuccess:^{        NSLog(@"已經有許可權,做相關操作,可以做讀取通訊錄等操作");    } failure:^{        NSLog(@"未得到許可權,做相關操作,可以做彈窗詢問等操作");    }];}

②彈出選擇視窗,點擊回調選中的資訊

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{    [[SXAddressBookManager manager]presentPageOnTarget:self chooseAction:^(SXPersonInfoEntity *person) {        NSLog(@"%@---%@",person.fullname,person.phoneNumber);    }];}

③獲得整個通訊錄資訊

self.personEntityArray = [[SXAddressBookManager manager]getPersonInfoArray];

④往通訊錄寫入一條資訊

[[SXAddressBookManager manager]creatItemWithName:@"雷克薩斯-北京諮詢電話" phone:@"010-88657869"];

demo的地址是

https://github.com/dsxNiubility/SXEasyAddressBook

這裡寫了我說的那三點常用,如果以後有一些剛需,會不斷補充。 董鉑然部落格園。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.