导入库#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 = 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)的更多相关文章

  1. 如何让你的App适配iOS7?

    随着苹果在2013年9月18日发布iOS7最新的系统以来,iOS各种设备升级到iOS7的数字就已经不断刷新记录.目前据外界统计iOS7设备装机量已经达到2.5亿部,已占iOS设备的64%.由此可见让自 ...

  2. 适配iOS7之—UITableView和UISearchBar

    iOS7中,如果用UITableViewStyleGrouped的话,里面的cell会比原来的拉长了,这样做应该是为了统一和UITableViewStylePlain风格时cell的大小一致,所以改用 ...

  3. iOS-scrollview及其子类适配iOS7

    问题描述: 在iOS7之后如果在导航控制器中所属的字控制器中嵌入scrollview及其子类的视图,当scrollview的尺寸太小的话不会调用返回cell的方法.控制器的嵌套层级结构如下图所示,着重 ...

  4. 适配ios7

    if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) { self.edgesForExtendedLayout = UIR ...

  5. IOS 启动画面和图标设置(适配IOS7 and Xcode5)

    关于IOS程序设置启动画面以及图标的设备目前主要为:IPhone设备 和IPad设备 IPhone启动画面以及图标的设置 目前IPhone的分辨率为:320X480.640X960.640X1136. ...

  6. iOS6 / iOS7 状态栏高度适配

    问题原因:iOS7的状态栏(status bar)不再占用单独的20px,所以假设你在iOS6上的界面布局是正常的,那么到了iOS7上就会变成以下这个样子:             左边是iOS6界面 ...

  7. [置顶] IOS7状态栏StatusBar官方标准适配方法

    IOS7状态栏StatusBar官方标准适配方法 hello,大家好,ios7正式版已经发布,相信大家都在以各种方式来适配ios7. 如果你已经下载了xcode5,正准备使用,你会发现各种布局的改变. ...

  8. iOS6和iOS7代码的适配(1)

    苹果的iOS7推出后,对于所有的应用来说都提出了一个天然的需求--适配不同版本的SDK.目前来说,用iOS6的SDK生成的应用,可以在iOS7的系统上跑,UI上也保持了原来的风格样式,这是苹果做的向下 ...

  9. IOS7 适配以及向下兼容问题

    1.所有的UIViewController加如下方法.     - (void) viewDidLayoutSubviews {         if ([[[UIDevice currentDevi ...

随机推荐

  1. Storm InvalidTopologyException: null

    异常信息: backtype.storm.generated.InvalidTopologyException: null at backtype.storm.daemon.common$valida ...

  2. ubuntu开机自动关闭独显,使用集成显卡

    我的本子是联想y470p-ise,因为是有双显卡,而ubuntu在开机后,双显卡默认是同时工作,会产生巨大的发热,导致很不爽.而且在ubuntu下基本我也不用独显,所以有开机关闭独显的需求. ubun ...

  3. Android内存泄露---检测工具篇

    内存使用是程序开发无法回避的一个问题.如果我们毫不在意肆意使用,总有一天会为此还账,且痛不欲生...所以应当防患于未然,把内存使用细化到平时的每一行代码中. 内存使用概念较大,本篇先讲对已有app如何 ...

  4. Web压力测试小工具:webbench、http_load、Siege、ab

    webbench 安装 下载地址:http://home.tiscali.cz/~cz210552/distfiles/webbench-1.5.tar.gz 或者 http://soft.vpser ...

  5. Java: 分解List<HashMap<String, String>>

    分解List<HashMap<String, String>> 的方法: List<HashMap<String, String>> mapList; ...

  6. IOS之TableViewCell重用机制解决上下刷新重复显示

    首先我是一个经验浅薄的iOS开发人员,这个问题想必许多初学者经常遇到这些问题,在面试中也会经常问到.现在我们一一解决. 首先我们要知道TableViewCell重用机制的原理是什么,我们抽象的理解为古 ...

  7. Swift2.2 看完这篇博客 你不想懂也会懂得----二叉树

    一:初衷 我自己也好奇,为什么莫名其妙的想起写这个,其实数据里面包含的结构和逻辑我自己觉得才是最原始经典的,最近也在学swift,就向着利用swift整理一些二叉树.自己刚开始的时候也是用OC看着别的 ...

  8. 读书笔记 effective c++ Item 14 对资源管理类的拷贝行为要谨慎

    1. 自己实现一个资源管理类 Item 13中介绍了 “资源获取之时也是初始化之时(RAII)”的概念,这个概念被当作资源管理类的“脊柱“,也描述了auto_ptr和tr1::shared_ptr是如 ...

  9. js加密

    在项目中,经常需要使用加密来保障数据的安全性,虽然可以通过在后台加密再传给前台,但这样无疑会增加后台的服务器的压力.所以在js中使用加密算法也就应运而生了. 一.base64加密 需要引入base64 ...

  10. devexpress实现多行表头(复合表头),附源代码

    在许多项目中都会涉及到复合表头(多行表头),这里给大家分享一个devexpress实现多重表头的案例. 1.第一步将表格类型由默认的gridview变为bandedgridview,如图所示: 2.第 ...