iOS开发之AddressBook框架详解
一、写在前面
首先,AddressBook框架是一个已经过时的框架,iOS9之后官方提供了Contacts框架来进行用户通讯录相关操作。尽管如此,AddressBook框架依然是一个非常优雅并且使用方便的通讯录帮助库。本篇博客只要总结AddressBook框架的相关使用方法。
在AddressBook框架中,两个最重要的数据模型为ABAddressbookRef与ABRecordRef。前者我们可以理解为通讯录的抽象对象,用它来具体操作通讯录的行为,后者可以理解为通讯录中记录的抽象对象,其中封装了联系人的相关信息。如下图所示:
二、关于用户权限申请
在应用程序内,若需要使用用户的通讯录权限需要征得用户的同意(毕竟通讯录属于用户隐私)。因此,在使用之前,开发者首先需要进行权限的申请,首先,需要在info.plist文件中添加如下键:
Privacy - Contacts Usage Description
使用如下代码进行使用权限的申请:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
if (status==kABAuthorizationStatusNotDetermined) { ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL); ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) { if (granted) { } CFRelease(addressBookRef); }); }
|
ABAuthorizationStatus是授权状态的枚举,意义如下:
1 2 3 4 5 6
| typedef CF_ENUM(CFIndex, ABAuthorizationStatus) { kABAuthorizationStatusNotDetermined = 0, kABAuthorizationStatusRestricted, kABAuthorizationStatusDenied, kABAuthorizationStatusAuthorized }
|
三、获取基础的通讯录信息
下面代码演示了如何获取基础的通讯录联系人信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| 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 *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);
|
打印信息如下:
关于可获取到的联系人属性,键值列举如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
| kABPersonFirstNameProperty
kABPersonLastNameProperty
kABPersonMiddleNameProperty
kABPersonPrefixProperty
kABPersonSuffixProperty
kABPersonNicknameProperty
kABPersonFirstNamePhoneticProperty
kABPersonLastNamePhoneticProperty
kABPersonMiddleNamePhoneticProperty
kABPersonOrganizationProperty
kABPersonDepartmentProperty
kABPersonJobTitleProperty
kABPersonEmailProperty
kABPersonBirthdayProperty
kABPersonNoteProperty
kABPersonCreationDateProperty
kABPersonModificationDateProperty
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
kABPersonURLProperty
kABPersonHomePageLabel
kABPersonRelatedNamesProperty
kABPersonFatherLabel kABPersonMotherLabel kABPersonParentLabel kABPersonBrotherLabel kABPersonSisterLabel kABPersonChildLabel kABPersonFriendLabel kABPersonSpouseLabel kABPersonPartnerLabel kABPersonAssistantLabel kABPersonManagerLabel
kABPersonSocialProfileProperty
kABPersonSocialProfileURLKey kABPersonSocialProfileServiceKey kABPersonSocialProfileUsernameKey kABPersonSocialProfileUserIdentifierKey kABPersonSocialProfileServiceTwitter kABPersonSocialProfileServiceSinaWeibo kABPersonSocialProfileServiceGameCenter kABPersonSocialProfileServiceFacebook kABPersonSocialProfileServiceMyspace kABPersonSocialProfileServiceLinkedIn kABPersonSocialProfileServiceFlickr
kABPersonAlternateBirthdayProperty
kABPersonAlternateBirthdayCalendarIdentifierKey kABPersonAlternateBirthdayEraKey kABPersonAlternateBirthdayYearKey kABPersonAlternateBirthdayMonthKey kABPersonAlternateBirthdayIsLeapMonthKey kABPersonAlternateBirthdayDayKey
|
四、关于ABMultiValueRef
如上所述,我们在获取联系人相关信息时,很多场景都会获取一组,例如对于电话号码,地址,邮箱这类的数据。在AddressBook框架中,这一组数据被封装为ABMultiValueRef对象。对于ABMultiValueRef对象,有如下方法可以对其进行处理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
|
ABPropertyType ABMultiValueGetPropertyType(ABMultiValueRef multiValue)
CFIndex ABMultiValueGetCount(ABMultiValueRef multiValue)
ABMultiValueCopyValueAtIndex(ABMultiValueRef multiValue, CFIndex index)
CFArrayRef ABMultiValueCopyArrayOfAllValues(ABMultiValueRef multiValue)
CFStringRef ABMultiValueCopyLabelAtIndex(ABMultiValueRef multiValue, CFIndex index)
ABMultiValueIdentifier ABMultiValueGetIdentifierAtIndex(ABMultiValueRef multiValue, CFIndex index)
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对象
ABRecordRef虽然很多时候,我们可以把它理解为联系人对象,但是其实并不正确,实际上它是一个抽象的记录对象,在AddressBook框架中有3种类型的ABRecordRef:
1 2 3 4 5
| enum { kABPersonType = 0, kABGroupType = 1, kABSourceType = 2 };
|
可以操作ABRecordRef的方法非常简单,无非读与写,如下:
1 2 3 4 5 6 7 8
| 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框架中的如下方法与联系人组操作相关:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 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的。除了最前面演示的申请权限的相关方法,如下列举了与ABAddressBookRef相关的其他常用函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 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);
|