首页 > 代码库 > 通讯录--(适配iOS7/8/9)
通讯录--(适配iOS7/8/9)
导入库#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
#pragma mark 点击 弹出通讯录
- (IBAction)contactClicked:(id)sender {
//1. 创建联系人选择控制器
ABPeoplePickerNavigationController *picker = [ABPeoplePickerNavigationController new];
//2. 设置代理,注意不是 Delegate
picker.peoplePickerDelegate = self;
//3. 模态视图弹出
[self presentViewController:picker animated:YES completion:nil];
//iOS 8之后如不想自动dismiss可以在弹出联系人控制器方法中加入如下代码:
if([[UIDevice currentDevice].systemVersion floatValue] >= 8.0){
picker.predicateForSelectionOfPerson = [NSPredicate predicateWithValue:false];
}
}
#pragma mark 代理方法介绍
//注意: iOS7 和 iOS8 的代理方法必须都写出来,这样才可以适配7 和 8
//以下1、2两个代理方法,如果同时实现, 只会运行第一个方法!
//1.第一个代理方法:选中某个联系人时调用(iOS8之后实现后再无法调用第2个的方法)
//参数 (ABRecordRef)person 介绍:
//一个联系人就是一个ABRecordRef对象,就相当于一条记录,每个联系人都有自己的属性,比如名字、电话、邮件等,使用ABRecordCopyValue函数可以从ABRecordRef中获得联系人的简单属性(参见下面简单属性的介绍)
//ABRecordCopyValue 从记录中取值函数:
//CFTypeRef ABRecordCopyValue(ABRecordRef record, ABPropertyID property)
//有2个参数:
//第1个参数是ABRecordRef实例
//第2个参数ABPropertyID是属性关键字,定义在ABPerson.h中,下面有介绍
//注意:使用ABRecordCopyValue可以从一条Person记录中获取到对应的值,但是后续还需要根据值的具体类型再加以处理(比如简单属性取的值不需要再处理,多重属性的值还需要通过其它函数再取值)
//ABPropertyID联系人属性介绍
//ABPropertyID 就是联系人的属性,所有的属性常量值都定义在了ABPerson.h头文件中
//联系人属性包括以下类型:
//(1)简单属性:姓 kABPersonLastNameProperty,名 kABPersonFirstNameProperty 等
//(2)组合属性:地址等 kABPersonAddressProperty
//(3)多重属性:电话号码 kABPersonPhoneProperty 、电子邮件 kABPersonEmailProperty 等
//联系人的有些属性值就没这么简单,一个属性可能会包含多个值,比如邮箱,分为工作邮箱、住宅邮箱、其他邮箱等,比如电话,分为工作电话、住宅电话、其他电话等
//如果是多重属性,那么ABRecordCopyValue函数返回的就是ABMultiValueRef类型的数据,例如邮箱或者电话
//// 取电话号码
//ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
//// 取记录数量
//NSInteger phoneCount = ABMultiValueGetCount(phones);
//// 遍历所有的电话号码
//for (NSInteger i = 0; i < phoneCount; i++) {...}
//获取多重属性的方法
//// 电话标签
//CFStringRef phoneLabel = ABMultiValueCopyLabelAtIndex(phones, i);
//// 本地化电话标签
//CFStringRef phoneLocalLabel = ABAddressBookCopyLocalizedLabel(phoneLabel);
//// 电话号码
//CFStringRef phoneNumber = ABMultiValueCopyValueAtIndex(phones, i);
#pragma mark 代理
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person{
//例子1:从记录中取姓,并转换为NSString类型
CFStringRef lastName = ABRecordCopyValue(person, kABPersonLastNameProperty);
NSString *lastNameStr = (__bridge NSString *)(lastName);
CFRelease(lastName); // 使用__bridge type 方法记得释放!
//例子2:获取电话号码, 电话返回的是多数据类型(可以获取到标签和电话号等信息)
// 获取电话,电话是多数据类型
ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
// 获取电话的个数
CFIndex count = ABMultiValueGetCount(phones);
// 遍历联系人,取出每个电话标签和电话号码,CF框架必须用for i循环
for (CFIndex i = 0 ; i < count; i++) {
// 获取联系电话的标签,使用__bridge_transfer方法不用释放
NSString *label = (__bridge_transfer NSString *)ABMultiValueCopyLabelAtIndex(phones, i);
NSLog(@"label: %@",label);
// 获取联系电话,使用CFBridgingRelease方法和上面功能一样也不需要释放
NSString *value = http://www.mamicode.com/CFBridgingRelease(ABMultiValueCopyValueAtIndex(phones, i));
NSLog(@"value: %@",value);
}
//phones 对象需要被释放
CFRelease(phones);
}
//例子3:获取通讯录中所有联系人信息
//- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person {
// // 1. 获取系统通讯录应用
// ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, nil);
// // 2. 获取所有联系人记录
// NSArray *array = (__bridge_transfer NSArray *)(ABAddressBookCopyArrayOfAllPeople(addressBook));
// for (NSInteger i = 0; i < array.count; i++) {
// // 取出一条记录
// ABRecordRef person = (__bridge ABRecordRef)(array[i]);
// // 取出个人记录中的详细信息
// NSString *firstNameLabel = (__bridge_transfer NSString *)(ABPersonCopyLocalizedPropertyName(kABPersonFirstNameProperty));
// NSString *firstName = (__bridge_transfer NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
// NSString *lastNameLabel =(__bridge_transfer NSString *)(ABPersonCopyLocalizedPropertyName(kABPersonLastNameProperty));
// NSString *lastName =(__bridge_transfer NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty));
// NSLog(@"%@ %@ - %@ %@", lastNameLabel, lastName, firstNameLabel, firstName);
// }
// CFRelease(addressBook);
//}
//关于Core Foundation 和 NSFundation 桥接的问题:
//注意:无论CF对象是否被引用,只要使用CF函数,就会产生CF对象留在内存中,如:ABMultiValueCopyValueAtIndex(phones, i)这一句,建议点击静态内存分析工具,可发现没有被释放的CF对象。
//桥接有三种方式:
//
//(__bridge type)(expression) : 只是让NSFoundation框架暂时使用CF框架对象,注意需要手动释放 Core Foundation 对象,用CFRelease( )函数。
//(__bridge_transfer type)(expression) / CFBridgingRelease(expression) : CF框架移交对象的管理权给NSFoundation框架,不需要手动释放对象
//前两种是将CF对象转NSFoundation,最后一个是NSFoundation转 CF对象,不常用
//(__bridge_retained <#CF type#>)(<#expression#>)
//2.第二个代理方法,选中联系人某个属性(详细的信息,如电话号码)的时候调用,注意和上面的方法只能实现一个,如同时实现无法跳转到联系人详情页面,优先上面的方法
//该方法可以获取具体的哪个电话号码,例如使用(充值话费)时不能使用上面方法,因为无法确定具体充值哪个号码
#pragma mark 选中联系人的某个属性的时候调用
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier {
// 获取该联系人多重属性--电话号
ABMutableMultiValueRef phoneMulti = ABRecordCopyValue(person, kABPersonPhoneProperty);
// 获取该联系人的名字,简单属性,只需ABRecordCopyValue取一次值
ABMutableMultiValueRef firstName = ABRecordCopyValue(person, kABPersonFirstNameProperty);
NSString *name = (__bridge NSString *)(firstName);
// 获取点击的联系人的电话
NSLog(@"联系人名字 : %@",name);
// 点击某个联系人电话后dismiss联系人控制器,并回调点击的数据
[self dismissViewControllerAnimated:YES completion:^{
// 从多重属性——电话号中取值,参数2是取点击的索引
NSString *aPhone = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(phoneMulti, ABMultiValueGetIndexForIdentifier(phoneMulti,identifier)) ;
// 获取点击的联系人的电话,也可以取标签等
NSLog(@"联系人电话 : %@",aPhone);
// 去掉电话号中的 "-"
aPhone = [aPhone stringByReplacingOccurrencesOfString:@"-" withString:@"" ];
NSLog(@"去掉-号 : %@",aPhone);
}];
}
//4.下面两个是 iOS7 选择联系人代理方法,iOS 8之前才会调用,适配iOS 7时实现,适配iOS 8之后使用上面两个方法
//1.返回YES,则会跳转到联系人详情页面,如果返回NO必须手动实现控制器dismiss方法
//- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person NS_DEPRECATED_IOS(2_0, 8_0);
//2.返回NO不会执行默认的操作,如:打电话,必须手动实现控制器dismiss方法
//- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier NS_DEPRECATED_IOS(2_0, 8_0);
通讯录--(适配iOS7/8/9)