首先,AddressBook框架是一個已通過時的框架,iOS9以後官方提供了Contacts框架來進行用戶通信錄相關操做。儘管如此,AddressBook框架依然是一個很是優雅而且使用方便的通信錄幫助庫。本篇博客只要總結AddressBook框架的相關使用方法。數組
在AddressBook框架中,兩個最重要的數據模型爲ABAddressbookRef與ABRecordRef。前者咱們能夠理解爲通信錄的抽象對象,用它來具體操做通信錄的行爲,後者能夠理解爲通信錄中記錄的抽象對象,其中封裝了聯繫人的相關信息。以下圖所示:框架
在應用程序內,若須要使用用戶的通信錄權限須要徵得用戶的贊成(畢竟通信錄屬於用戶隱私)。所以,在使用以前,開發者首先須要進行權限的申請,首先,須要在info.plist文件中添加以下鍵:ide
Privacy - Contacts Usage Description函數
使用以下代碼進行使用權限的申請:工具
//獲取用戶受權狀態 ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus(); //若是還沒有獲取過受權 進行受權申請 if (status==kABAuthorizationStatusNotDetermined) { //建立通信錄對象 這個方法中第1個參數爲預留參數 傳NULL 便可 第2個參數能夠傳一個CFErrorRef的指針 ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL); //請求受權 ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) { if (granted) {//請求受權頁面用戶贊成受權 //能夠進行使用 } //釋放內存 CFRelease(addressBookRef); }); }
ABAuthorizationStatus是受權狀態的枚舉,意義以下:編碼
typedef CF_ENUM(CFIndex, ABAuthorizationStatus) { kABAuthorizationStatusNotDetermined = 0, // 還沒有申請過受權 kABAuthorizationStatusRestricted, // 受權被限制 沒法使用 kABAuthorizationStatusDenied, // 用戶拒絕受權 kABAuthorizationStatusAuthorized // 已經受權 }
下面代碼演示瞭如何獲取基礎的通信錄聯繫人信息:url
//獲取通信錄 ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL); //獲取聯繫人數量 CFIndex personCount = ABAddressBookGetPersonCount(addressBook); //拿到全部聯繫人 CFArrayRef peopleArray = ABAddressBookCopyArrayOfAllPeople(addressBook); for (int i = 0; i < personCount; i++) { //獲取記錄 ABRecordRef person = CFArrayGetValueAtIndex(peopleArray, i); //拿到姓名 //姓 須要轉換成NSString類型 NSString *lastNameValue = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty); //名 NSString *firstNameValue = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty); NSLog(@"%@:%@",lastNameValue,firstNameValue); //拿到電話 電話可能有多個 ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty); //解析電話數據 CFIndex phoneCount = ABMultiValueGetCount(phones); for (int j = 0; j < phoneCount ; j++) { //電話標籤本地化(例如是住宅,工做等) NSString *phoneLabel = (__bridge_transfer NSString *)ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(phones, j)); //拿到標籤下對應的電話號碼 NSString *phoneValue = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(phones, j); NSLog(@"%@:%@",phoneLabel,phoneValue); } CFRelease(phones); //郵箱 可能多個 ABMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty); CFIndex emailCount = ABMultiValueGetCount(emails); for (int k = 0; k < emailCount; k++) { NSString *emailLabel = (__bridge_transfer NSString *)ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(emails, k)); NSString *emailValue = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(emails, k); NSLog(@"%@:%@",emailLabel,emailValue); } NSLog(@"=============="); CFRelease(emails); } CFRelease(addressBook); CFRelease(peopleArray);
打印信息以下:spa
關於可獲取到的聯繫人屬性,鍵值列舉以下:指針
//名 kABPersonFirstNameProperty //姓 kABPersonLastNameProperty //中間名 kABPersonMiddleNameProperty //前綴 用戶在存儲聯繫人時 能夠添加自定義的前綴 例如 女士 男士等等 kABPersonPrefixProperty //後綴 kABPersonSuffixProperty //暱稱 kABPersonNicknameProperty //姓發音說明字段 用戶自定義的 kABPersonFirstNamePhoneticProperty //名發音說明字段 用戶自定義的 kABPersonLastNamePhoneticProperty //中間名發音說明字段 用戶自定義的 kABPersonMiddleNamePhoneticProperty //公司名 kABPersonOrganizationProperty //部門名 kABPersonDepartmentProperty //頭銜 kABPersonJobTitleProperty //電子郵件信息 返回一組 須要手動解析 kABPersonEmailProperty //返回生日信息 日期對象 kABPersonBirthdayProperty //筆記信息 kABPersonNoteProperty //記錄的建立日期 kABPersonCreationDateProperty //記錄的最後修改日期 kABPersonModificationDateProperty //地址信息 返回 一組 /* 例如: ABMultiValueRef address = ABRecordCopyValue(person, kABPersonAddressProperty); for (int j=0; j<ABMultiValueGetCount(address); j++) { //地址類型 NSString *type = (__bridge NSString *)(ABMultiValueCopyLabelAtIndex(address, j)); NSDictionary * temDic = (__bridge NSDictionary *)(ABMultiValueCopyValueAtIndex(address, j)); //地址字符串,能夠按需求格式化 NSString * adress = [NSString stringWithFormat:@"國家:%@\n省:%@\n市:%@\n街道:%@\n郵編:%@",[temDic valueForKey:(NSString*)kABPersonAddressCountryKey],[temDic valueForKey:(NSString*)kABPersonAddressStateKey],[temDic valueForKey:(NSString*)kABPersonAddressCityKey],[temDic valueForKey:(NSString*)kABPersonAddressStreetKey],[temDic valueForKey:(NSString*)kABPersonAddressZIPKey]]; } */ kABPersonAddressProperty //地址字典中的街道信息鍵 kABPersonAddressStreetKey //地址字典中的城市信息鍵 kABPersonAddressCityKey //地址字典中的地區信息鍵 kABPersonAddressStateKey //地址字典中的壓縮碼信息鍵 kABPersonAddressZIPKey //地址字典中的國家信息鍵 kABPersonAddressCountryKey //地址字典中的國家編碼信息鍵 kABPersonAddressCountryCodeKey //獲取 一組 記念日日期 kABPersonDateProperty //從具體的日期實體中獲取記念日 標籤 kABPersonAnniversaryLabel //獲取一組電話號碼 kABPersonPhoneProperty //下面這些對應電話類型 kABPersonPhoneMobileLabel kABPersonPhoneIPhoneLabel kABPersonPhoneMainLabel kABPersonPhoneHomeFAXLabel kABPersonPhoneWorkFAXLabel kABPersonPhoneOtherFAXLabel kABPersonPhonePagerLabel //獲取社交相關信息 kABPersonInstantMessageProperty //下面這些對應社交平臺 kABPersonInstantMessageServiceKey kABPersonInstantMessageServiceYahoo kABPersonInstantMessageServiceJabber kABPersonInstantMessageServiceMSN kABPersonInstantMessageServiceICQ kABPersonInstantMessageServiceAIM kABPersonInstantMessageServiceQQ kABPersonInstantMessageServiceGoogleTalk kABPersonInstantMessageServiceSkype kABPersonInstantMessageServiceFacebook kABPersonInstantMessageServiceGaduGadu //社交用戶名 kABPersonInstantMessageUsernameKey //獲取一組url kABPersonURLProperty //url相關標籤 kABPersonHomePageLabel //關聯信息 kABPersonRelatedNamesProperty //關聯信息相關的標籤 kABPersonFatherLabel kABPersonMotherLabel kABPersonParentLabel kABPersonBrotherLabel kABPersonSisterLabel kABPersonChildLabel kABPersonFriendLabel kABPersonSpouseLabel kABPersonPartnerLabel kABPersonAssistantLabel kABPersonManagerLabel //獲取社交帳戶相關 kABPersonSocialProfileProperty //社交帳戶相關key kABPersonSocialProfileURLKey kABPersonSocialProfileServiceKey kABPersonSocialProfileUsernameKey kABPersonSocialProfileUserIdentifierKey kABPersonSocialProfileServiceTwitter kABPersonSocialProfileServiceSinaWeibo kABPersonSocialProfileServiceGameCenter kABPersonSocialProfileServiceFacebook kABPersonSocialProfileServiceMyspace kABPersonSocialProfileServiceLinkedIn kABPersonSocialProfileServiceFlickr //週期性日期信息 kABPersonAlternateBirthdayProperty //週期性日期相關鍵 kABPersonAlternateBirthdayCalendarIdentifierKey kABPersonAlternateBirthdayEraKey kABPersonAlternateBirthdayYearKey kABPersonAlternateBirthdayMonthKey kABPersonAlternateBirthdayIsLeapMonthKey kABPersonAlternateBirthdayDayKey
如上所述,咱們在獲取聯繫人相關信息時,不少場景都會獲取一組,例如對於電話號碼,地址,郵箱這類的數據。在AddressBook框架中,這一組數據被封裝爲ABMultiValueRef對象。對於ABMultiValueRef對象,有以下方法能夠對其進行處理:code
//獲取內部封裝值的類型 /* enum { kABInvalidPropertyType = 0x0, // 無效 kABStringPropertyType = 0x1, // 字符串 kABIntegerPropertyType = 0x2, // 整數 kABRealPropertyType = 0x3, // 屬性 kABDateTimePropertyType = 0x4, // 時間 kABDictionaryPropertyType = 0x5, // 字典 kABMultiStringPropertyType = kABMultiValueMask | kABStringPropertyType, // 聚合字符串 kABMultiIntegerPropertyType = kABMultiValueMask | kABIntegerPropertyType, // 聚合整型 kABMultiRealPropertyType = kABMultiValueMask | kABRealPropertyType, // 聚合屬性 kABMultiDateTimePropertyType = kABMultiValueMask | kABDateTimePropertyType, // 聚合時間 kABMultiDictionaryPropertyType = kABMultiValueMask | kABDictionaryPropertyType, // 聚合字典 }; */ ABPropertyType ABMultiValueGetPropertyType(ABMultiValueRef multiValue) //獲取其中封裝的值的個數 CFIndex ABMultiValueGetCount(ABMultiValueRef multiValue) //根據索引獲取值 ABMultiValueCopyValueAtIndex(ABMultiValueRef multiValue, CFIndex index) //獲取全部的值 組成數組 CFArrayRef ABMultiValueCopyArrayOfAllValues(ABMultiValueRef multiValue) //根據索引獲取標籤 CFStringRef ABMultiValueCopyLabelAtIndex(ABMultiValueRef multiValue, CFIndex index) //根據ID獲取值 ABMultiValueIdentifier ABMultiValueGetIdentifierAtIndex(ABMultiValueRef multiValue, CFIndex index) //根據ID 獲取索引 CFIndex ABMultiValueGetIndexForIdentifier(ABMultiValueRef multiValue, ABMultiValueIdentifier identifier) //獲取第一個值 CFIndex ABMultiValueGetFirstIndexOfValue(ABMultiValueRef multiValue, CFTypeRef value) //下面這些與寫聯繫人信息相關 //建立一個可變的數據對象 ABMutableMultiValueRef ABMultiValueCreateMutable(ABPropertyType type) //爲某個標籤添加值 bool ABMultiValueAddValueAndLabel(ABMutableMultiValueRef multiValue, CFTypeRef value, CFStringRef label, ABMultiValueIdentifier *outIdentifier) //在某個索引處插入 標籤和值 bool ABMultiValueInsertValueAndLabelAtIndex(ABMutableMultiValueRef multiValue, CFTypeRef value, CFStringRef label, CFIndex index, ABMultiValueIdentifier *outIdentifier) //刪除某個索引處的標籤和值 bool ABMultiValueRemoveValueAndLabelAtIndex(ABMutableMultiValueRef multiValue, CFIndex index) //替換某個索引處的值 bool ABMultiValueReplaceValueAtIndex(ABMutableMultiValueRef multiValue, CFTypeRef value, CFIndex index) //替換某個索引處的標籤 bool ABMultiValueReplaceLabelAtIndex(ABMutableMultiValueRef multiValue, CFStringRef label, CFIndex index)
ABRecordRef雖然不少時候,咱們能夠把它理解爲聯繫人對象,可是其實並不正確,實際上它是一個抽象的記錄對象,在AddressBook框架中有3種類型的ABRecordRef:
enum { kABPersonType = 0, //聯繫人類型 kABGroupType = 1, //組類型 kABSourceType = 2 //資源類型 };
能夠操做ABRecordRef的方法很是簡單,無非讀與寫,以下:
//獲取記錄類型 ABRecordType ABRecordGetRecordType(ABRecordRef record); //獲取記錄中的數據 CFTypeRef ABRecordCopyValue(ABRecordRef record, ABPropertyID property); //設置記錄中的數據 bool ABRecordSetValue(ABRecordRef record, ABPropertyID property, CFTypeRef value, CFErrorRef* error); //刪除記錄中的數據 bool ABRecordRemoveValue(ABRecordRef record, ABPropertyID property, CFErrorRef* error);
在iOS系統的聯繫人應用中,咱們能夠對聯繫人進行分組,以下圖所示:
AddressBook框架中的以下方法與聯繫人組操做相關:
//建立一個聯繫人組記錄 ABRecordRef ABGroupCreate(void); //在指定的資源中建立 ABRecordRef ABGroupCreateInSource(ABRecordRef source); //獲取資源 ABRecordRef ABGroupCopySource(ABRecordRef group); //獲取組中的全部成員 CFArrayRef ABGroupCopyArrayOfAllMembers(ABRecordRef group); //根據指定的排序方法獲取組中全部成員 CFArrayRef ABGroupCopyArrayOfAllMembersWithSortOrdering(ABRecordRef group, ABPersonSortOrdering sortOrdering); //向組中添加成員 bool ABGroupAddMember(ABRecordRef group, ABRecordRef person, CFErrorRef* error); //刪除組中的成員 bool ABGroupRemoveMember(ABRecordRef group, ABRecordRef member, CFErrorRef* error); //根據某條記錄獲取組 ABRecordRef ABAddressBookGetGroupWithRecordID(ABAddressBookRef addressBook, ABRecordID recordID); //獲取通信錄中全部組的個數 CFIndex ABAddressBookGetGroupCount(ABAddressBookRef addressBook); //獲取通信錄中全部組 CFArrayRef ABAddressBookCopyArrayOfAllGroups(ABAddressBookRef addressBook); CFArrayRef ABAddressBookCopyArrayOfAllGroupsInSource(ABAddressBookRef addressBook, ABRecordRef source);
前面介紹了許多操做聯繫人,操做組的方法,全部這些操做的基礎都是基於一個通信錄對象ABAddressBookRef的。除了最前面演示的申請權限的相關方法,以下列舉了與ABAddressBookRef相關的其餘經常使用函數:
//存儲通信錄 bool ABAddressBookSave(ABAddressBookRef addressBook, CFErrorRef* error); //獲取通信錄是否有未保存的更改 bool ABAddressBookHasUnsavedChanges(ABAddressBookRef addressBook); //向通信錄中添加一條記錄 bool ABAddressBookAddRecord(ABAddressBookRef addressBook, ABRecordRef record, CFErrorRef* error); //移除通信錄中的一條記錄 bool ABAddressBookRemoveRecord(ABAddressBookRef addressBook, ABRecordRef record, CFErrorRef* error); //註冊通信錄發生變化時的外部監聽 void ABAddressBookRegisterExternalChangeCallback(ABAddressBookRef addressBook, ABExternalChangeCallback callback, void *context); //移除通信錄發生變化時的外部監聽 void ABAddressBookUnregisterExternalChangeCallback(ABAddressBookRef addressBook, ABExternalChangeCallback callback, void *context); //將未保存的更改重置 void ABAddressBookRevert(ABAddressBookRef addressBook); //工具方法,進行標籤的本地化轉換 CFStringRef ABAddressBookCopyLocalizedLabel(CFStringRef label);