//由於本人閒來無事,爲了打發時間,把以前項目的中一些知識點整理一下,下面是 獲取通訊錄的相關知識點,內容簡單,希望對各位有所幫助,有何問題,歡迎留言(PS:雖然不一定回覆您或者幫您解決,但好歹您老人家不要憋壞了)
/**
*獲取通訊錄信息
倒入頭文件 #import <AddressBook/AddressBook.h>
在build phases 裏面 導入 addressBook.framework 框架
*隨着apple對用戶隱私的越來越重視,IOS系統的權限設置也更加嚴格,在獲取系統通訊錄之前,我們必須獲得用戶的授權。權限申請代碼示例如下:
*參考博客://http://www.open-open.com/code/view/1432302834146
*/
//授權 :如果不授權 是讀不出通訊錄信息的
- (void)getInfoOfAddressBookWithAuthorize
{
//這個變量用於記錄授權是否成功,即用戶是否允許我們訪問通訊錄
int __block tip=0;
//聲明一個通訊簿的引用
ABAddressBookRef addBook =nil;
//因爲在IOS6.0之後和之前的權限申請方式有所差別,這裏做個判斷
if ([[UIDevice currentDevice].systemVersion floatValue]>=6.0) {
//創建通訊簿的引用
addBook=ABAddressBookCreateWithOptions(NULL, NULL);
//創建一個出事信號量爲0的信號
dispatch_semaphore_t sema=dispatch_semaphore_create(0);
//申請訪問權限
ABAddressBookRequestAccessWithCompletion(addBook, ^(bool greanted, CFErrorRef error) {
//greanted爲YES是表示用戶允許,否則爲不允許
if (!greanted) {
tip=1;
}
//發送一次信號
dispatch_semaphore_signal(sema);
});
//等待信號觸發
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}else{
//IOS6之前
addBook =ABAddressBookCreate();
}
if (tip) {
//做一個友好的提示
UIAlertView * alart = [[UIAlertView alloc]initWithTitle:@"溫馨提示" message:@"請您設置允許APP訪問您的通訊錄\nSettings>General>Privacy" delegate:self cancelButtonTitle:@"確定" otherButtonTitles:nil, nil];
[alart show];
return;
}
/*
幾點注意: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回調中獲取的,所以我們需要在外面做一個線程等待
*/
// [self writeContractPerson:addBook];
[self deleteInfo:addBook];
[self addressBookMessager:addBook];
CFRelease(addBook);
}
/*
* 四、重中之重-關於內存管理
上面的代碼爲了演示方便,創建的全部引用都沒有釋放,勢必是造成內存泄露,在我們用ABAddressBookCreate()創建一個引用對象時,切記無論ARC還MRC,要用CFRelease()進行釋放引用,例如上面的例子,我們需要加上這句代碼
CFRelease(addBook);
如果你耐心的看到了這裏,我想你一定明白了我爲什麼不在前邊的代碼裏說明這個問題,因爲在ARC項目普及的現在,這的確是重中之重。
*/
// 獲取通訊錄信息
- (void)addressBookMessager:(ABAddressBookRef )addBook
{
//隨着apple對用戶隱私的越來越重視,IOS系統的權限設置也更加嚴格,在獲取系統通訊錄之前,我們必須獲得用戶的授權。權限申請代碼示例如下:
NSString *allName = nil;
//獲取所有聯繫人的數組
CFArrayRef allLinkPeople = ABAddressBookCopyArrayOfAllPeople(addBook);
//獲取聯繫人總數
CFIndex number = ABAddressBookGetPersonCount(addBook);
//進行遍歷
for (NSInteger i=0; i<number; i++) {
//獲取聯繫人對象的引用
ABRecordRef people = CFArrayGetValueAtIndex(allLinkPeople, i);
//獲取當前聯繫人名字
NSString*firstName=(__bridge NSString *)(ABRecordCopyValue(people, kABPersonFirstNameProperty));
//獲取當前聯繫人姓氏
NSString*lastName=(__bridge NSString *)(ABRecordCopyValue(people, kABPersonLastNameProperty));
//獲取當前聯繫人中間名
NSString*middleName=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonMiddleNameProperty));
//獲取當前聯繫人的名字前綴
NSString*prefix=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonPrefixProperty));
//獲取當前聯繫人的名字後綴
NSString*suffix=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonSuffixProperty));
//獲取當前聯繫人的暱稱
NSString*nickName=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonNicknameProperty));
//獲取當前聯繫人的名字拼音
NSString*firstNamePhoneic=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonFirstNamePhoneticProperty));
//獲取當前聯繫人的姓氏拼音
NSString*lastNamePhoneic=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonLastNamePhoneticProperty));
//獲取當前聯繫人的中間名拼音
NSString*middleNamePhoneic=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonMiddleNamePhoneticProperty));
//獲取當前聯繫人的公司
NSString*organization=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonOrganizationProperty));
//獲取當前聯繫人的職位
NSString*job=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonJobTitleProperty));
//獲取當前聯繫人的部門
NSString*department=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonDepartmentProperty));
//獲取當前聯繫人的生日
NSDate*birthday=(__bridge NSDate*)(ABRecordCopyValue(people, kABPersonBirthdayProperty));
NSMutableArray * emailArr = [[NSMutableArray alloc]init];
//獲取當前聯繫人的郵箱 注意是數組
ABMultiValueRef emails= ABRecordCopyValue(people, kABPersonEmailProperty);
for (NSInteger j=0; j<ABMultiValueGetCount(emails); j++) {
[emailArr addObject:(__bridge NSString *)(ABMultiValueCopyValueAtIndex(emails, j))];
}
//獲取當前聯繫人的備註
NSString*notes=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonNoteProperty));
//獲取當前聯繫人的電話 數組
NSMutableArray * phoneArr = [[NSMutableArray alloc]init];
ABMultiValueRef phones= ABRecordCopyValue(people, kABPersonPhoneProperty);
for (NSInteger j=0; j<ABMultiValueGetCount(phones); j++) {
[phoneArr addObject:(__bridge NSString *)(ABMultiValueCopyValueAtIndex(phones, j))];
}
/*
*對我需要的數據進行處理,這個自己去加以判斷選擇
*/
if (firstName == nil && middleName == nil && lastName == nil) {
allName = [phoneArr firstObject];
}else {//如果沒有名字的時候,在通訊錄裏面用電話號碼去顯示
if (firstName == nil) {
firstName = @"";
}
if (lastName == nil) {
lastName = @"";
}
if (middleName == nil) {
middleName = @"";
}
allName = [NSString stringWithFormat:@"%@%@%@",firstName,middleName,lastName];
}
[self.dataList addObject:allName];
//獲取創建當前聯繫人的時間 注意是NSDate
NSDate*creatTime=(__bridge NSDate*)(ABRecordCopyValue(people, kABPersonCreationDateProperty));
//獲取最近修改當前聯繫人的時間
NSDate*alterTime=(__bridge NSDate*)(ABRecordCopyValue(people, kABPersonModificationDateProperty));
//獲取地址
ABMultiValueRef address = ABRecordCopyValue(people, 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]];
}
//獲取當前聯繫人頭像圖片
NSData*userImage=(__bridge NSData*)(ABPersonCopyImageData(people));
//獲取當前聯繫人紀念日
NSMutableArray * dateArr = [[NSMutableArray alloc]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];
}
}
/*
* 一定要釋放內存
*/
CFRelease(allLinkPeople);
}
/**
*通訊錄“寫”的相關操作
*/
- (void)writeContractPerson:(ABAddressBookRef )addBook {
//創建一個聯繫人引用
ABRecordRef person = ABPersonCreate();
NSString *firstName = @"哈1";
NSString *lastName = @"哈1";
NSData *birthday = nil;
// 電話號碼數組
NSArray *phones = [NSArray arrayWithObjects:@"123",@"456",nil];
// 電話號碼對應的名稱
NSArray *labels = [NSArray arrayWithObjects:@"iphone",@"home",nil];
//這裏的字段和上面的字段完全相同
// 設置名字屬性
ABRecordSetValue(person, kABPersonFirstNameProperty,(__bridge CFStringRef)firstName, NULL);
// 設置姓氏屬性
ABRecordSetValue(person, kABPersonLastNameProperty, (__bridge CFStringRef)lastName, NULL);
// 設置生日屬性
ABRecordSetValue(person, kABPersonBirthdayProperty,(__bridge CFDateRef)birthday, NULL);
// 字典引用
ABMultiValueRef dic =ABMultiValueCreateMutable(kABMultiStringPropertyType);
// 添加電話號碼與其對應的名稱內容
for (int i = 0; i < [phones count]; i ++) {
ABMultiValueIdentifier obj = ABMultiValueAddValueAndLabel(dic,(__bridge CFStringRef)[phones objectAtIndex:i], (__bridge CFStringRef)[labels objectAtIndex:i], &obj);
}
// 設置phone屬性
ABRecordSetValue(person, kABPersonPhoneProperty, dic, NULL);
// 將新建的聯繫人添加到通訊錄中
ABAddressBookAddRecord(addBook, person, NULL);
// 保存通訊錄數據
ABAddressBookSave(addBook, NULL);
CFRelease(person);
/*
*2、修改聯繫人
* 修改聯繫人的操作就是將獲取和添加和在一起,先獲取到相應的聯繫人引用,重設其屬性字段即可。
*/
}
//刪除聯繫人
- (void)deleteInfo:(ABAddressBookRef )addBook {
//獲取所有聯繫人
NSArray *array = (__bridge NSArray*)ABAddressBookCopyArrayOfAllPeople(addBook);
// 遍歷所有的聯繫人
for (id obj in array) {
ABRecordRef people = (__bridge ABRecordRef)obj;
NSString *firstName = (__bridge NSString*)ABRecordCopyValue(people, kABPersonFirstNameProperty);
NSString *lastName = (__bridge NSString*)ABRecordCopyValue(people, kABPersonLastNameProperty);
if ([firstName isEqualToString:@"哈"] &&[lastName isEqualToString:@"哈"]) {
ABAddressBookRemoveRecord(addBook, people,NULL);
}
}
// 保存修改的通訊錄對象
ABAddressBookSave(addBook, NULL);
}
/*
場景一:直接選擇一個聯繫人的電話號碼《這種情景時彈出一個系統的VC,然後可以去選擇通訊錄一條信息,點擊後有回彈出一個VC,您在選擇後,可以獲取相關聯繫人的信息,這時他會自動的反悔到上個頁面,可以按返回按鈕,回到最初您寫的的頁面》您可以在 協議方法裏面做一些相關的處理
這裏不需要先獲取所有的聯繫人自己做聯繫人列表,直接使用系統自帶的AddressBookUI/ABPeoplePickerNavigationController.h就好。
首先需要引入如下三個文件
#import <AddressBookUI/ABPeoplePickerNavigationController.h>
#import <AddressBook/ABPerson.h>
#import <AddressBookUI/ABPersonViewController.h>
然後初始化ABPeoplePickerNavigationController。
協議方法
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker didSelectPerson:(ABRecordRef)person NS_AVAILABLE_IOS(8_0);
// Called after a property has been selected by the user.
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier NS_AVAILABLE_IOS(8_0);
// Called after the user has pressed cancel.
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker;
// Deprecated, use predicateForSelectionOfPerson and/or -peoplePickerNavigationController:didSelectPerson: instead.
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person NS_DEPRECATED_IOS(2_0, 8_0);
// Deprecated, use predicateForSelectionOfProperty and/or -peoplePickerNavigationController:didSelectPerson:property:identifier: instead.
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier NS_DEPRECATED_IOS(2_0, 8_0);
*/
- (void)memorandum {
ABPeoplePickerNavigationController *nav = [[ABPeoplePickerNavigationController alloc] init];
nav.peoplePickerDelegate = self;
if([[UIDevice currentDevice].systemVersion floatValue] >= 8.0){
nav.predicateForSelectionOfPerson = [NSPredicate predicateWithValue:false];
}
[self presentViewController:nav animated:YES completion:nil];
/*
在iOS8之後,需要添加nav.predicateForSelectionOfPerson = [NSPredicate predicateWithValue:false];這一段代碼,否則選擇聯繫人之後會直接dismiss,不能進入詳情選擇電話。
*/
}
//取消選擇 用戶按下取消後調用。
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker
{
[peoplePicker dismissViewControllerAnimated:YES completion:nil];
}
//iOS8下
// Called after a person has been selected by the user .一個人被選中的人被用戶選中。
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier {
ABMultiValueRef phone = ABRecordCopyValue(person, kABPersonPhoneProperty);
long index = ABMultiValueGetIndexForIdentifier(phone,identifier);
NSString *phoneNO = (__bridge NSString *)ABMultiValueCopyValueAtIndex(phone, index);
if ([phoneNO hasPrefix:@"+"]) {
phoneNO = [phoneNO substringFromIndex:3];
}
phoneNO = [phoneNO stringByReplacingOccurrencesOfString:@"-" withString:@""];
NSLog(@"%@", phoneNO);
// if (phone && [ZXValidateHelper checkTel:phoneNO]) {
// phoneNum = phoneNO;
// [self.tableView reloadData];
// [peoplePicker dismissViewControllerAnimated:YES completion:nil];
// return;
// }
}
//一個人被選中的人被用戶選中。
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker didSelectPerson:(ABRecordRef)person
{
ABPersonViewController *personViewController = [[ABPersonViewController alloc] init];
personViewController.displayedPerson = person;
[peoplePicker pushViewController:personViewController animated:YES];
}
// ios 7 下
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
return YES;
}
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
{
ABMultiValueRef phone = ABRecordCopyValue(person, kABPersonPhoneProperty);
long index = ABMultiValueGetIndexForIdentifier(phone,identifier);
NSString *phoneNO = (__bridge NSString *)ABMultiValueCopyValueAtIndex(phone, index);
if ([phoneNO hasPrefix:@"+"]) {
phoneNO = [phoneNO substringFromIndex:3];
}
phoneNO = [phoneNO stringByReplacingOccurrencesOfString:@"-" withString:@""];
NSLog(@"%@", phoneNO);
// if (phone && [ZXValidateHelper checkTel:phoneNO]) {
// phoneNum = phoneNO;
// [self.tableView reloadData];
// [peoplePicker dismissViewControllerAnimated:YES completion:nil];
// return NO;
// }
return YES;
}