iOS開發之AddressBook框架詳解

iOS開發之AddressBook框架詳解

1、寫在前面

    首先,AddressBook框架是一個已通過時的框架,iOS9以後官方提供了Contacts框架來進行用戶通信錄相關操做。儘管如此,AddressBook框架依然是一個很是優雅而且使用方便的通信錄幫助庫。本篇博客只要總結AddressBook框架的相關使用方法。數組

    在AddressBook框架中,兩個最重要的數據模型爲ABAddressbookRef與ABRecordRef。前者咱們能夠理解爲通信錄的抽象對象,用它來具體操做通信錄的行爲,後者能夠理解爲通信錄中記錄的抽象對象,其中封裝了聯繫人的相關信息。以下圖所示:框架

2、關於用戶權限申請

    在應用程序內,若須要使用用戶的通信錄權限須要徵得用戶的贊成(畢竟通信錄屬於用戶隱私)。所以,在使用以前,開發者首先須要進行權限的申請,首先,須要在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            // 已經受權
}

3、獲取基礎的通信錄信息

    下面代碼演示瞭如何獲取基礎的通信錄聯繫人信息: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

4、關於ABMultiValueRef

    如上所述,咱們在獲取聯繫人相關信息時,不少場景都會獲取一組,例如對於電話號碼,地址,郵箱這類的數據。在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)

5、ABRecordRef對象

    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);

6、聯繫人組

    在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);

7、重中之重——ABAddressBookRef對象

    前面介紹了許多操做聯繫人,操做組的方法,全部這些操做的基礎都是基於一個通信錄對象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);
相關文章
相關標籤/搜索