一、許可權註冊
隨著apple對使用者隱私的越來越重視,IOS系統的許可權設定也更加嚴格,在獲取系統通訊錄之前,我們必須獲得使用者的授權。許可權申請程式碼示例如下:
//這個變數用於記錄授權是否成功,即使用者是否允許我們訪問通訊錄
int __block tip=0;
AddressBookRef a
//宣告一個通訊簿的引用
A
BddBook =nil;
0之後和之前的許可權申請方式有所差別,這裡做個判斷
if ([[UID
//因為在IOS6
.evice currentDevice].systemVersion floatValue]>=6.0) {
//建立通訊簿的引用
ddressBookCreateWithOptions(NULL, NULL);
//建立一個出事訊號
addBook=AB
A量為0的訊號
dispatch_semaphore_t sema=dispatch_semaphore_create(0);
k, ^(bool greant
//申請訪問許可權
ABAddressBookRequestAccessWithCompletion(addBo
oed, CFErrorRef error) {
//greanted為YES是表示使用者允許,否則為不允許
if (!greanted) {
tip=1;
}
spatch_semaphore_signal(sema);
});
//等待訊號觸發
;
}else{
//IOS6之前
addBook =ABAddressBookCr
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER
)eate();
}
if (tip) {
//做一個友好的提示
lloc]initWithTitle:@"溫馨提示" message:@"請您設定允許APP訪問您的通訊錄\nSettings>General>Privacy" delegate:self cancelButtonTitle:@"確定" otherButtonTitles:nil, nil];
[alart show];
return;
}
UIAlertView * alart = [[UIAlertView
a
幾點注意:1、dispatch_semaphore_t三個相關的操作為
dispatch_semaphore_create 建立一個訊號
dispatch_semaphore_signal 傳送一個訊號
dispatch_semaphore_wait 等待訊號觸發
dispatch_semaphore_create()建立一個訊號,後面可以跟一個引數,表示訊號量,當訊號量正值時,dispatch_semaphore_wait後面的程式碼會被執行,否則程式將會一直等待在dispatch_semaphore_wait。 dispatch_semaphore_signal的作用是傳送一個訊號,會使訊號量加1,相對的,dispatch_semaphore_wait執行後會使訊號量減1.
2、因為是否被授權是在ABAddressBookRequestAccessWithCompletion的block回撥中獲取的,所以我們需要在外面做一個執行緒等待。
二、獲取通訊錄聯絡人詳細資訊
//獲取所有聯絡人的陣列
CFArrayRef allLinkPeople = ABAddressBookCopyArrayOfAllPeople(addBook);
//獲取聯絡人總數
CFIndex number = ABAddressBookGetPersonCount(addBook);
AB
//進行遍歷
for (NSInteger i=0; i<number; i++) {
//獲取聯絡人物件的引用
取當前聯絡人名字
NSString*firstName=(__bridge NSString *)(ABR
RecordRef people = CFArrayGetValueAtIndex(allLinkPeople, i);
//
獲ecordCopyValue(people, kABPersonFirstNameProperty));
//獲取當前聯絡人姓氏
kABPersonLastNameProperty));
//獲取當前聯絡人中間名
leName=(__bridge NSString*)(ABR
NSString*mid
d
NSString*lastName=(__bridge NSString *)(ABRecordCopyValue(people,
ecordCopyValue(people, kABPersonMiddleNameProperty));
//獲取當前聯絡人的名字字首
NSString*prefix=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonPrefixProperty));
e NSString*)(ABRecordC
//獲取當前聯絡人的名字字尾
NSString*suffix=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonSuffixProperty));
//獲取當前聯絡人的暱稱
NSString*nickName=(__brid
gopyValue(people, kABPersonNicknameProperty));
//獲取當前聯絡人的名字拼音
NSString*firstNamePhoneic=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonFirstNamePhoneticProperty));
mePhoneic=(__bridge NS
//獲取當前聯絡人的姓氏拼音
NSString*lastNamePhoneic=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonLastNamePhoneticProperty));
//獲取當前聯絡人的中間名拼音
NSString*middleN
aString*)(ABRecordCopyValue(people, kABPersonMiddleNamePhoneticProperty));
//獲取當前聯絡人的公司
NSString*organization=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonOrganizationProperty));
people, kABPersonDep
//獲取當前聯絡人的職位
NSString*job=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonJobTitleProperty));
//獲取當前聯絡人的部門
NSString*department=(__bridge NSString*)(ABRecordCopyValue
(artmentProperty));
//獲取當前聯絡人的生日
NSString*birthday=(__bridge NSDate*)(ABRecordCopyValue(people, kABPersonBirthdayProperty));
NSMutableArray * emailArr = [[NSMutableArray alloc]init];
t:(__bridge NSString *)(AB
//獲取當前聯絡人的郵箱 注意是陣列
ABMultiValueRef emails= ABRecordCopyValue(people, kABPersonEmailProperty);
for (NSInteger j=0; j<ABMultiValueGetCount(emails); j++) {
[emailArr addObje
cMultiValueCopyValueAtIndex(emails, j))];
}
//獲取當前聯絡人的備註
NSString*notes=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonNoteProperty));
//獲取當前聯絡人的電話 陣列
eGetCount(phones); j++) {
[phonerr addObject:(__bridg
NSMutableArray * phoneArr = [[NSMutableArray alloc]init];
ABMultiValueRef phones= ABRecordCopyValue(people, kABPersonPhoneProperty);
for (NSInteger j=0; j<ABMultiVal
ue NSString *)(ABMultiValueCopyValueAtIndex(phones, j))];
}
//獲取建立當前聯絡人的時間 注意是NSDate
NSDate*creatTime=(__bridge NSDate*)(ABRecordCopyValue(people, kABPersonCreationDateProperty));
//獲取最近修改當前聯絡人的時間
; j<ABMultiValueGetCount(address); j++) {
//地址型別
g * type = (__bridge NSStr
NSStri
n
NSDate*alterTime=(__bridge NSDate*)(ABRecordCopyValue(people, kABPersonModificationDateProperty));
//獲取地址
ABMultiValueRef address = ABRecordCopyValue(people, kABPersonAddressProperty);
for (int j=
0ing *)(ABMultiValueCopyLabelAtIndex(address, j));
NSDictionary * temDic = (__bridge NSDictionary *)(ABMultiValueCopyValueAtIndex(address, j));
//地址字串,可以按需求格式化
ABPersonAddressStateKey],[temDic valueForKey:(NSString*)kABPersonAddressCityKey],[temDic valueForKey:(NSString*)kABPersonAddressStreetKey],[temDic valueForKey:(NSString*)kABPersonAddressZIPKey]];
}
//獲取當前聯絡人頭像圖片
NSData*userImage=(__bridge NSData*)(ABPersonCopyImageData(people));
//獲取當前聯絡人紀念日
NSMutableArray * dateArr = [[NSMutableArray all
NSString * adress = [NSString stringWithFormat:@"國家:%@\n省:%@\n市:%@\n街道:%@\n郵編:%@",[temDic valueForKey:(NSString*)kABPersonAddressCountryKey],[temDic valueForKey:(NSString*)
koc]init];
ABMultiValueRef dates= ABRecordCopyValue(people, kABPersonDateProperty);
for (NSInteger j=0; j<ABMultiValueGetCount(dates); j++) {
//獲取紀念日日期
NSDate * data =(__bridge NSDate*)(ABMultiValueCopyValueAtIndex(dates, j));
//獲取紀念日名稱
NSString * str =(__bridge NSString*)(ABMultiValueCopyLabelAtIndex(dates, j));
NSDictionary * temDic = [NSDictionary dictionaryWithObject:data forKey:str];
[dateArr addObject:temDic];
}
一點擴充套件:相同的方法,可以獲取關聯人資訊,社交資訊,郵箱資訊,各種型別的電話資訊,欄位如下:
//相關人,組織欄位
const ABPropertyID kABPersonKindProperty;
const CFNumberRef kABPersonKindPerson;
tion;
/ 電話相關欄位
/AB_EXTERN const ABPropertyI
const CFNumberRef kABPersonKindOrganiz
aD kABPersonPhoneProperty;
AB_EXTERN const CFStringRef kABPersonPhoneMobileLabel;
kABPersonPhoneMainLabel;
AB_EXTERN const CFStringRef
AB_EXTERN const CFStringRef kABPersonPhoneIPhoneLabel
AB_EXTERN const CFStringRe
fkABPersonPhoneHomeFAXLabel;
AB_EXTERN const CFStringRef kABPersonPhoneWorkFAXLabel;
ABPersonPhonePagerLabel;
// 即時聊天資訊相關欄位
AB_EXTERN cons
t
AB_EXTERN const CFStringRef kABPersonPhoneOtherFAXLabel
AB_EXTERN const CFStringRef
k ABPropertyID kABPersonInstantMessageProperty;
AB_EXTERN const CFStringRef kABPersonInstantMessageServiceKey;
viceJabber;
AB_EXTERN const CFStringRef kABPersonInstantMessageS
AB_EXTERN const CFStringRef kABPersonInstantMessageServiceYahoo;
AB_EXTERN const CFStringRef kABPersonInstantMessageSe
rerviceMSN;
AB_EXTERN const CFStringRef kABPersonInstantMessageServiceICQ;
AB_EXTERN const CFStringRef kABPersonInstantMessageServiceAIM;
ERN const CFStringRef kABPersonInstantMessageServiceSkype;
AB
AB_EXTERN const CFStringRef kABPersonInstantMessageServiceQQ
AB_EXTERN const CFStringRef kABPersonInstantMessageServiceGoogleTalk;
AB_EX
T_EXTERN const CFStringRef kABPersonInstantMessageServiceFacebook;
AB_EXTERN const CFStringRef kABPersonInstantMessageServiceGaduGadu;
AB_EXTERN const CFStringRef kABPersonInstantMessageUsernameKey;
// 個人網頁相關欄位
AB_EXTERN const ABPropertyID kABPersonURLProperty;
AB_EXTERN const CFStringRef kABPersonHomePageLabel;
//相關人姓名欄位
AB_EXTERN const ABPropertyID kABPersonRelatedNamesProperty;
AB_EXTERN
const CFStringRef kABPersonFatherLabel; // Father
AB_EXTERN const CFStringRef kABPersonMotherLabel; // Mother
AB_EXTERN const CFStringRef kABPersonParentLabel; // Parent
// Child
AB_EXTERN const CFStringRef kABPersonFriendLabel;
AB_EXTERN const CFStringRef kABPersonBrotherLabel; // Brother
AB_EXTERN const CFStringRef kABPersonSisterLabel; // Sister
AB_EXTERN const CFStringRef kABPersonChildLabel;
// Friend
AB_EXTERN const CFStringRef kABPersonSpouseLabel; // Spouse
AB_EXTERN const CFStringRef kABPersonPartnerLabel; // Partner
AB_EXTERN const CFStringRef kABPersonAssistantLabel; // Assistant
AB_EXTERN const CFStringRef kABPersonManagerLabel; // Manager
三、通訊錄“寫”的相關操作
看到上面讀取資訊的程式碼,你可能覺得一陣目炫,其實只是欄位比較長,邏輯還是很簡單的,同樣,寫的操作與之類似,建立,修改,刪除,是我們對通訊錄“寫”的常用操作。
1、建立一個聯絡人
//建立一個聯絡人引用
ABRecordRef person = ABPersonCreate();
NSString *firstName = @"哈";
NSString *lastName = @"哈";
es = [NSArray arrayWithObjects:@"123",@"456",nil];
yWithObjects:@"i
// 電話號碼對應的名稱
NSArray *labels = [NSArray arr
aphone",@"home",nil];
//這裡的欄位和上面的欄位完全相同
// 設定名字屬性
_bridge CFStringRef)firstName, NULL);
// 設定姓氏屬性
tValue(person, kABPersonLastN
ABRecordS
e
ABRecordSetValue(person, kABPersonFirstNameProperty,(
_ameProperty, (__bridge CFStringRef)lastName, NULL);
// 設定生日屬性
DateRef)birthday, NULL);
// 字典引用
alueRef dic =ABMultiValueCreateMutable(kAB
ABMulti
V
ABRecordSetValue(person, kABPersonBirthdayProperty,(__bridge C
FMultiStringPropertyType);
// 新增電話號碼與其對應的名稱內容
for (int i = 0; i < [phones count]; i ++) {
s objectAtIndex:i], (__bridge CFStringRef)[labels objectAtIndex:i], &obj);
}
// 設定phone屬性
rson, kABPersonPhoneProperty, dic, NULL);
// 將新
ABRecordSetValue(p
e
ABMultiValueIdentifier obj = ABMultiValueAddValueAndLabel(dic,(__bridge CFStringRef)[phon
e建的聯絡人新增到通訊錄中
ABAddressBookAddRecord(addBook, person, NULL);
// 儲存通訊錄資料
ABAddressBookSave(addBook, NULL);
2、修改聯絡人
修改聯絡人的操作就是將獲取和新增和在一起,先獲取到相應的聯絡人引用,重設其屬性欄位即可。
3.刪除聯絡人
//獲取所有聯絡人
NSArray *array = (__bridge NSArray*)ABAddressBookCopyArrayOfAllPeople(addBook);
// 遍歷所有的聯絡人
for (id obj in array) {
ordRef)obj;
NSString *firstName = (__bridge NSS
ABRecordRef people = (__bridge ABRe
ctring*)ABRecordCopyValue(people, kABPersonFirstNameProperty);
lue(people, kABPersonLastNameProperty);
if ([firstName isEqualToString:@"哈"] &&[lastName isEqu
NSString *lastName = (__bridge NSString*)ABRecordCopyV
aalToString:@"哈"]) {
ABAddressBookRemoveRecord(addBook, people,NULL);
}
}
// 儲存修改的通訊錄物件
ABAddressBookSave(addBook, NULL);
四、重中之重-關於記憶體管理
上面的程式碼為了演示方便,建立的全部引用都沒有釋放,勢必是造成記憶體洩露,在我們用ABAddressBookCreate()建立一個引用物件時,切記無論ARC還MRC,要用CFRelease()進行釋放引用,例如上面的例子,我們需要加上這句程式碼
CFRelease(addBook);
如果你耐心的看到了這裡,我想你一定明白了我為什麼不在前邊的程式碼裡說明這個問題,因為在ARC專案普及的現在,這的確是重中之重。