通訊錄簡介
通訊錄使用場景:
- 電商類的 App轰绵,設置收貨人電話號碼票摇。
- 即時通訊類 App亥揖,添加手機聯(lián)系人好友奈梳。
通訊錄獲取方案:
一杈湾、iOS 9 以前的通訊錄框架
-
AddressBookUI.framework
框架- 提供了聯(lián)系人列表界面、聯(lián)系人詳情界面攘须、添加聯(lián)系人界面等漆撞。
- 一般用于選擇聯(lián)系人。
-
AddressBook.framework
框架- 純 C 語言的 API于宙,僅僅是獲得聯(lián)系人數(shù)據(jù)浮驳。
- 沒有提供 UI 界面展示,需要自己搭建聯(lián)系人展示界面捞魁。
- 里面的數(shù)據(jù)類型大部分基于 Core Foundation 框架至会,使用起來炒雞復雜。
二谱俭、 iOS 9 以后最新通訊錄框架
-
ContactsUI.framework
框架奉件。- 擁有
AddressBookUI.framework
框架的所有功能,使用起來更加的面向對象昆著。
- 擁有
-
Contacts.framework
框架县貌。- 擁有
AddressBook.framework
框架的所有功能,不再是 C 語言的 API凑懂,使用起來非常簡單煤痕。
- 擁有
iOS 9 以前的通訊錄框架
AddressBookUI
實現(xiàn)步驟
一、創(chuàng)建選擇聯(lián)系人的控制器
// 創(chuàng)建聯(lián)系人選擇控制器
ABPeoplePickerNavigationController *pvc = [[ABPeoplePickerNavigationController alloc] init];
二征候、設置代理(用來接收用戶選擇的聯(lián)系人信息)
// 設置代理
pvc.peoplePickerDelegate = self;
三杭攻、彈出聯(lián)系人控制器
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined)
{
ABAddressBookRef bookRef = ABAddressBookCreate();
ABAddressBookRequestAccessWithCompletion(bookRef, ^(bool granted, CFErrorRef error) {
if (granted)
{
NSLog(@"授權成功!");
[self presentViewController:pvc animated:YES completion:nil];
}
else
{
NSLog(@"授權失敗!");
}
});
}
else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized)
{
[self presentViewController:pvc animated:YES completion:nil];
}
四、實現(xiàn)代理方法
// 選擇某個聯(lián)系人時調(diào)用
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker didSelectPerson:(ABRecordRef)person
{
NSLog(@"選中聯(lián)系人");
CFStringRef firstName = ABRecordCopyValue(person, kABPersonFirstNameProperty);
CFStringRef lastName = ABRecordCopyValue(person, kABPersonLastNameProperty);
NSString *fir = CFBridgingRelease(firstName);
NSString *las = CFBridgingRelease(lastName);
NSLog(@"%@---%@", fir, las);
ABMultiValueRef multi = ABRecordCopyValue(person, kABPersonPhoneProperty);
CFIndex count = ABMultiValueGetCount(multi);
for (int i = 0; i < count; i++)
{
NSString *label = (__bridge_transfer NSString *)ABMultiValueCopyLabelAtIndex(multi, i);
NSString *phone =(__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(multi, i);
NSLog(@"%@---%@", label, phone);
}
}
Core Foundation 對象手動管理內(nèi)存疤坝,如果是 Create兆解、Copy、Retain 等字樣創(chuàng)建的對象跑揉,需要手動 CFRelease锅睛。類似 Objective-C 的 MRC。
拓展:__bridge
历谍,__bridge_retained
和 __bridge_transfer
三個轉換關鍵字的區(qū)別现拒。
-
__bridge
只做類型轉換,但是不修改對象(內(nèi)存)管理權望侈; -
__bridge_retained
(也可以使用CFBridgingRetain
)將 Objective-C 的對象轉換為 Core Foundation 的對象印蔬,同時將對象(內(nèi)存)的管理權交給我們,后續(xù)需要使用CFRelease
或者相關方法來釋放對象脱衙; -
__bridge_transfer
(也可以使用CFBridgingRelease
)將 Core Foundation 的對象轉換為 Objective-C 的對象侥猬,同時將對象(內(nèi)存)的管理權交給 ARC例驹。
五、在對應的代理方法中獲取聯(lián)系人信息
// 1.選擇聯(lián)系人時使用(不展開詳情)
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person;
// 2.選擇聯(lián)系人某個屬性時調(diào)用(展開詳情)
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier;
// 3.取消選中聯(lián)系人時調(diào)用
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker;
注意:選擇聯(lián)系人的不展開詳情(代理方法1)和展開詳情(代理方法2)的代理方法都寫了的時候退唠,展開詳情的代理方法就不執(zhí)行鹃锈。
AddressBook
一、請求授權
從 iOS 6 開始瞧预,需要得到用戶的授權才能訪問通訊錄屎债,因此在使用之前,需要檢查用戶是否已經(jīng)授權垢油。
// 獲得通訊錄的授權狀態(tài)
ABAddressBookGetAuthorizationStatus()
授權狀態(tài)
用戶還沒有決定是否授權你的程序進行訪問:
kABAuthorizationStatusNotDetermined
iOS 設備上一些許可配置阻止程序與通訊錄數(shù)據(jù)庫進行交互:
kABAuthorizationStatusRestricted
用戶明確的拒絕了你的程序對通訊錄的訪問:
kABAuthorizationStatusDenied
用戶已經(jīng)授權給你的程序對通訊錄進行訪問:
kABAuthorizationStatusAuthorized
// 判斷當前的授權狀態(tài)是否是用戶還未選擇的狀態(tài)
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined)
{
ABAddressBookRef bookRef = ABAddressBookCreate();
ABAddressBookRequestAccessWithCompletion(bookRef, ^(bool granted, CFErrorRef error) {
if (granted)
{
NSLog(@"授權成功!");
}
else
{
NSLog(@"授權失敗!");
}
});
}
二盆驹、判斷授權狀態(tài)
如果已授權,則繼續(xù)滩愁;未授權召娜,則提示用戶,并返回惊楼。
// 判斷當前的授權狀態(tài)
if (ABAddressBookGetAuthorizationStatus() != kABAuthorizationStatusAuthorized)
{
NSLog(@"您的通訊錄暫未允許訪問,請去設置->隱私里面授權!");
return;
}
三秸讹、創(chuàng)建通訊錄對象
// 創(chuàng)建通訊錄對象
ABAddressBookRef bookRef = ABAddressBookCreate();
四檀咙、從通信錄對象中, 獲取所有的聯(lián)系人
// 獲取通訊錄中所有的聯(lián)系人
CFArrayRef arrayRef = ABAddressBookCopyArrayOfAllPeople(bookRef);
五、遍歷所有的聯(lián)系人
// 遍歷所有聯(lián)系人
CFIndex count = CFArrayGetCount(arrayRef);
for (int i = 0; i < count; i++)
{
ABRecordRef record = CFArrayGetValueAtIndex(arrayRef, i);
// 獲取姓名
NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(record, kABPersonFirstNameProperty);
NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(record, kABPersonLastNameProperty);
NSLog(@"firstName = %@, lastName = %@", firstName, lastName);
// 獲取電話號碼
ABMultiValueRef multiValue = ABRecordCopyValue(record, kABPersonPhoneProperty);
CFIndex count = ABMultiValueGetCount(multiValue);
for (int i = 0; i < count; i ++)
{
NSString *label = (__bridge_transfer NSString *)ABMultiValueCopyLabelAtIndex(multiValue, i);
NSString *phone = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(multiValue, i);
NSLog(@"label = %@, phone = %@", label, phone);
}
CFRelease(multiValue);
}
六璃诀、釋放不再使用的對象
CFRelease(bookRef);
CFRelease(arrayRef);
聯(lián)系人屬性定義
所有的屬性常量值都定義在了 ABPerson.h
頭文件中弧可。
聯(lián)系人屬性包括以下類型:
- 簡單屬性:姓、名等
- 多重屬性:電話號碼劣欢、電子郵件等
- 組合屬性:地址等
注意:使用
ABRecordCopyValue
可以從一條 Person 記錄中獲取到對應的記錄棕诵,但是后續(xù)處理則需要根據(jù)記錄的具體類型加以區(qū)分。
簡單屬性
一個聯(lián)系人就是一個 ABRecordRef
凿将,每個聯(lián)系人都有自己的屬性校套,比如名字、電話牧抵、郵件等笛匙。
使用 ABRecordCopyValue
函數(shù)可以從 ABRecordRef
中獲得聯(lián)系人的簡單屬性(例如:一個字符串)。
ABRecordCopyValue
函數(shù)接收 2 個參數(shù)犀变。
第 1 個參數(shù)是 ABRecordRef
實例妹孙。
第 2 個參數(shù)是屬性關鍵字,定義在 ABPerson.h
中获枝。
ABPersonCopyLocalizedPropertyName
函數(shù)可以根據(jù)指定的關鍵字獲取對應的標簽文本蠢正。
獲得所有的聯(lián)系人數(shù)據(jù)
// 獲取所有聯(lián)系人記錄
CFArrayRef array = ABAddressBookCopyArrayOfAllPeople(addressBook);
NSInteger count = CFArrayGetCount(array);
for (NSInteger i = 0; i < count; ++i) {
// 取出一條記錄
ABRecordRef person = CFArrayGetValueAtIndex(array, i);
// 取出個人記錄中的詳細信息
// 名
CFStringRef firstNameLabel = ABPersonCopyLocalizedPropertyName(kABPersonFirstNameProperty);
CFStringRef firstName = ABRecordCopyValue(person, kABPersonFirstNameProperty);
CFStringRef lastNameLabel = ABPersonCopyLocalizedPropertyName(kABPersonLastNameProperty);
// 姓
CFStringRef lastName = ABRecordCopyValue(person, kABPersonLastNameProperty);
NSLog(@"%@ %@ - %@ %@", lastNameLabel, lastName, firstNameLabel, firstName);
}
CoreFoundation 與 Foundation之間的橋接
// 1. 獲取通訊錄引用
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, nil);
// 2. 獲取所有聯(lián)系人記錄
NSArray *array = (__bridge NSArray *)(ABAddressBookCopyArrayOfAllPeople(addressBook));
for (NSInteger i = 0; i < array.count; i++) {
// 取出一條記錄
ABRecordRef person = (__bridge ABRecordRef)(array[i]);
// 取出個人記錄中的詳細信息
NSString *firstNameLabel = (__bridge NSString *)(ABPersonCopyLocalizedPropertyName(kABPersonFirstNameProperty));
NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
NSString *lastNameLabel = (__bridge NSString *)(ABPersonCopyLocalizedPropertyName(kABPersonLastNameProperty));
NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty));
NSLog(@"%@ %@ - %@ %@", lastNameLabel, lastName, firstNameLabel, firstName);
}
CFRelease(addressBook);
多重屬性
聯(lián)系人的有些屬性值就沒這么簡單,一個屬性可能會包含多個值
比如郵箱省店,分為工作郵箱嚣崭、住宅郵箱笨触、其他郵箱等
比如電話,分為工作電話有鹿、住宅電話旭旭、其他電話等
如果是復雜屬性,那么 ABRecordCopyValue
函數(shù)返回的就是 ABMultiValueRef
類型的數(shù)據(jù)葱跋,例如郵箱或者電話
// 取電話號碼
ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
// 取記錄數(shù)量
NSInteger phoneCount = ABMultiValueGetCount(phones);
// 遍歷所有的電話號碼
for (NSInteger i = 0; i < phoneCount; i++)
{
}
獲取復雜屬性的方法
// 電話標簽
CFStringRef phoneLabel = ABMultiValueCopyLabelAtIndex(phones, i);
// 本地化電話標簽
CFStringRef phoneLocalLabel = ABAddressBookCopyLocalizedLabel(phoneLabel);
// 電話號碼
CFStringRef phoneNumber = ABMultiValueCopyValueAtIndex(phones, i);
添加聯(lián)系人的步驟
添加聯(lián)系人的步驟:
- 通過
ABPersonCreate
函數(shù)創(chuàng)建一個新的聯(lián)系人(返回ABRecordRef
)持寄。 - 通過
ABRecordSetValue
函數(shù)設置聯(lián)系人的屬性。 - 通過
ABAddressBookAddRecord
函數(shù)將聯(lián)系人添加到通訊錄數(shù)據(jù)庫中娱俺。 - 通過
ABAddressBookSave
函數(shù)保存剛才所作的修改稍味。
可以通過 ABAddressBookHasUnsavedChanges
函數(shù)判斷是否有未保存的修改
當決定是否更改通訊錄數(shù)據(jù)庫后,你可以分別使用 AbAddressBookSave
或 ABAddressBookRevert
方式來保存或放棄更改 荠卷。
添加群組的步驟
添加群組的步驟大體和添加聯(lián)系人一致:
- 通過
ABPersonCreate
函數(shù)創(chuàng)建一個新的組模庐。(返回ABRecordRef
) - 通過
ABRecordSetValue
函數(shù)設置組名。 - 通過
ABAddressBookAddRecord
函數(shù)將組添加到通訊錄數(shù)據(jù)庫中油宜。 - 通過
ABAddressBookSave
函數(shù)保存剛才所作的修改掂碱。
操作聯(lián)系人的頭像
想操作聯(lián)系人的頭像,有以下函數(shù)
BPersonHasImageData
判斷通訊錄中的聯(lián)系人是否有圖片
ABPersonCopyImageData
取得圖片數(shù)據(jù)(假如有的話)
ABPersonSetImageData
設置聯(lián)系人的圖片數(shù)據(jù)
通訊錄的修改回調(diào)
// 創(chuàng)建通訊錄
self.addressBook = ABAddressBookCreate();
// 注冊通知
ABAddressBookRegisterExternalChangeCallback(self.addressBook, _addressBookChange, nil);
// 處理收到通知的 Action
void _addressBookChange(ABAddressBookRef addressBook, CFDictionaryRef info, void *context)
{
}
- (void)dealloc
{
// 注銷通知
ABAddressBookUnregisterExternalChangeCallback(self.addressBook, _addressBookChange, nil);
// 釋放對象
CFRelease(self.addressBook);
}
iOS 9 以后的通訊錄新框架
iOS 9 之前操作通訊錄還是比較麻煩的慎冤,iOS 9 以后蘋果推出了全新的通訊錄框架疼燥,使用起來更加的面向對象。
CNContactUI
實現(xiàn)步驟
一蚁堤、創(chuàng)建選擇聯(lián)系人的控制器
// 創(chuàng)建聯(lián)系人選擇控制器
CNMutableContact *contact = [[CNMutableContact alloc] init];
CNLabeledValue *labelValue = [CNLabeledValue labeledValueWithLabel:CNLabelPhoneNumberMobile
ontact.phoneNumbers = @[labelValue]; value:[CNPhoneNumber phoneNumberWithStringValue:phoneNum]];
CNContactViewController *contactController = [CNContactViewController viewControllerForNewContact:contact];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:contactController];
二醉者、設置代理(用來接收用戶選擇的聯(lián)系人信息)
// 設置代理
contactController.delegate = self;
三、彈出聯(lián)系人控制器
[controller presentViewController:nav animated:YES completion:nil];
四披诗、實現(xiàn)代理方法
// 選擇某個聯(lián)系人時調(diào)用
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperty:(CNContactProperty *)contactProperty
{
CNContact *contact = contactProperty.contact;
NSString *name = [CNContactFormatter stringFromContact:contact style:CNContactFormatterStyleFullName];
CNPhoneNumber *phoneValue= contactProperty.value;
NSString *phoneNumber = phoneValue.stringValue;
NSLog(@"%@--%@",name, phoneNumber);
}
五撬即、在對應的代理方法中獲取聯(lián)系人信息
// 1.選擇聯(lián)系人時使用(不展開詳情)
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContact:(CNContact *)contact;
// 2.選擇聯(lián)系人某個屬性時調(diào)用(展開詳情)
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperty:(CNContactProperty *)contactProperty;
// 3.取消選中聯(lián)系人時調(diào)用
- (void)contactPickerDidCancel:(CNContactPickerViewController *)picker;
注意:與 AddressBookUI 一樣,選擇聯(lián)系人的不展開詳情(代理方法1)和展開詳情(代理方法2)的代理方法都寫了的時候呈队,展開詳情的代理方法就不執(zhí)行剥槐。
CNContact
實現(xiàn)步驟
一、請求授權
// 獲得通訊錄的授權狀態(tài)
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts]
授權狀態(tài)
用戶還沒有決定是否授權你的程序進行訪問:
CNAuthorizationStatusNotDetermined
iOS 設備上一些許可配置阻止程序與通訊錄數(shù)據(jù)庫進行交互:
CNAuthorizationStatusRestricted
用戶明確的拒絕了你的程序對通訊錄的訪問:
CNAuthorizationStatusDenied
用戶已經(jīng)授權給你的程序對通訊錄進行訪問:
CNAuthorizationStatusAuthorized
// 判斷當前的授權狀態(tài)是否是用戶還未選擇的狀態(tài)
if (status == CNAuthorizationStatusNotDetermined)
{
CNContactStore *store = [CNContactStore new];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted)
{
NSLog(@"授權成功!");
}
else
{
NSLog(@"授權失敗!");
}
}];
}
二掂咒、判斷授權狀態(tài)
如果已授權才沧,則繼續(xù);未授權绍刮,則提示用戶温圆,并返回。
// 判斷當前的授權狀態(tài)
if (status != CNAuthorizationStatusAuthorized)
{
NSLog(@"您的通訊錄暫未允許訪問孩革,請去設置->隱私里面授權!");
return;
}
三岁歉、創(chuàng)建通訊錄對象
// 創(chuàng)建通訊錄對象
CNContactStore *contactStore = [CNContactStore new];
四、設置訪問的屬性 Key,每個 Key 對應一個屬性锅移,iOS 9 新增熔掺,如果沒有設置,訪問該屬性就會崩潰非剃。
// 姓名前綴
CNContactNamePrefixKey
// 名
CNContactGivenNameKey
// 中間名
CNContactMiddleNameKey
// 姓
CNContactFamilyNameKey
// 婚前姓
CNContactPreviousFamilyNameKey
// 姓名后綴
CNContactNameSuffixKey
// 昵稱
CNContactNicknameKey
// 公司
CNContactOrganizationNameKey
// 部門
CNContactDepartmentNameKey
// 職位
CNContactJobTitleKey
// 名字拼音或音標
CNContactPhoneticGivenNameKey
// 中間名拼音或音標
CNContactPhoneticMiddleNameKey
// 姓拼音或音標
CNContactPhoneticFamilyNameKey
// 公司拼音或音標
CNContactPhoneticOrganizationNameKey
// 生日
CNContactBirthdayKey
// 農(nóng)歷
CNContactNonGregorianBirthdayKey
// 備注
CNContactNoteKey
// 圖片
CNContactImageDataKey
// 縮略圖
CNContactThumbnailImageDataKey
// 圖片是否允許訪問
CNContactImageDataAvailableKey
// 類型
CNContactTypeKey
// 號碼
CNContactPhoneNumbersKey
// 電子郵件
CNContactEmailAddressesKey
// 地址
CNContactPostalAddressesKey
// 日期
CNContactDatesKey
// URL
CNContactUrlAddressesKey
// 關聯(lián)人
CNContactRelationsKey
// 社交
CNContactSocialProfilesKey
// 即時通訊
CNContactInstantMessageAddressesKey
NSArray *keys = @[CNContactPhoneNumbersKey,CNContactGivenNameKey];
五置逻、從通信錄對象中, 獲取所有的聯(lián)系人,并遍歷
// 獲取通訊錄中所有的聯(lián)系人
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:keys];
[contactStore enumerateContactsWithFetchRequest:request error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
// 獲取姓名
NSString *firstName = contact.familyName;
NSString *lastName = contact.givenName;
NSLog(@"%@--%@",firstName,lastName);
// 獲取電話號碼
for (CNLabeledValue *labeledValue in contact.phoneNumbers)
{
CNPhoneNumber *phoneValue = labeledValue.value;
NSString *phoneNumber = phoneValue.stringValue;
NSString *label = [CNLabeledValue localizedStringForLabel:labeledValue.label];
NSLog(@"%@--%@",label,phoneNumber);
}
}];
通訊錄的修改回調(diào)
// 注冊通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_contactStoreDidChange) name:CNContactStoreDidChangeNotification object:nil]
// 處理收到通知的 Action
- (void)_contactStoreDidChange
{
}
- (void)dealloc
{
// 注銷通知
[[NSNotificationCenter defaultCenter] removeObserver:self name:CNContactStoreDidChangeNotification object:nil];
}
當 App 活躍(前臺+后臺活動期間)的時候备绽,當通訊錄修改的時候券坞,會收到通知
當 App 不活躍的時候(掛起的時候),App 收不到通知肺素;而是恨锚,當 App 到前臺的時候收到延遲的通知。
LJContactManager
介紹
LJContanctManager 是我寫的一款操作通訊錄的類庫倍靡,iOS 9 之前使用的是 AddressBook 和 AddressBookUI 系統(tǒng)庫猴伶,iOS 9 之后使用蘋果新推出的 Contacts 和 ContactsUI 框架。
安裝
CocoaPods
- 在 Podfile 中添加
pod 'LJContactManager'
塌西。 - 執(zhí)行
pod install
或pod update
他挎。 - 導入 <LJContactManager.h>。
手動安裝
- 下載 LJContactManager 文件夾內(nèi)的所有內(nèi)容捡需。
- 將 LJContactManager 內(nèi)的源文件添加(拖放)到你的工程雇盖。
- 導入
LJContactManager.h
。
使用
主要提供以下的方法:
- 選擇聯(lián)系人
/**
選擇聯(lián)系人
@param controller 控制器
@param completcion 回調(diào)
*/
- (void)selectContactAtController:(UIViewController *)controller
complection:(void (^)(NSString *name, NSString *phone))completcion;
- 創(chuàng)建新聯(lián)系人
/**
創(chuàng)建新聯(lián)系人
@param phoneNum 手機號
@param controller 當前 Controller
*/
- (void)createNewContactWithPhoneNum:(NSString *)phoneNum controller:(UIViewController *)controller;
- 添加到現(xiàn)有聯(lián)系人
/**
添加到現(xiàn)有聯(lián)系人
@param phoneNum 手機號
@param controller 當前 Controller
*/
- (void)addToExistingContactsWithPhoneNum:(NSString *)phoneNum controller:(UIViewController *)controller;
- 獲取聯(lián)系人列表(未分組的通訊錄)
/**
獲取聯(lián)系人列表(未分組的通訊錄)
@param completcion 回調(diào)
*/
- (void)accessContactsComplection:(void (^)(BOOL succeed, NSArray <LJPerson *> *contacts))completcion;
- 獲取聯(lián)系人列表(已分組的通訊錄)
/**
獲取聯(lián)系人列表(已分組的通訊錄)
@param completcion 回調(diào)
*/
- (void)accessSectionContactsComplection:(void (^)(BOOL succeed, NSArray <LJSectionPerson *> *contacts, NSArray <NSString *> *keys))completcion;
- 通訊錄變更回調(diào)(未分組的通訊錄)
/**
通訊錄變更回調(diào)(未分組的通訊錄)
*/
@property (nonatomic, copy) void (^contactsChangeHanlder) (BOOL succeed, NSArray <LJPerson *> *newContacts);
- 通訊錄變更回調(diào)(已分組的通訊錄)
/**
通訊錄變更回調(diào)(已分組的通訊錄)
*/
@property (nonatomic, copy) void (^sectionContactsHanlder) (BOOL succeed, NSArray <LJSectionPerson *> *newSectionContacts, NSArray <NSString *> *keys);
最后
由于筆者水平有限栖忠,文中如果有錯誤的地方汞窗,或者有更好的方法贡避,還望大神指出。
附上本文的所有 demo 下載鏈接闪朱,【GitHub】薛匪。
如果你看完后覺得對你有所幫助捐川,還望在 GitHub 上點個 star。贈人玫瑰逸尖,手有余香古沥。