ios-访问通讯录及Core Foundation和Foundation的桥接
来源:互联网 发布:软件外包管理 编辑:程序博客网 时间:2024/06/06 16:56
有两个框架可以去访问通讯录一个是AddressBook,AddressBookUI。其中在ios9的时候AddressBookUI框架不推荐使用已经废弃。
其中AddressBookUI提供了联系人列表界面和联系人详情界面、和添加联系人。
AddressBook的话就是需要我们自己去搭建界面的,这里面包含的就是纯C语言的API,仅仅只能获取联系人的数据
里面的数据类型大部分都是基于Core Foundation框架的。
注意的是,我们要访问用户的通讯录的话,应该在Info.plist文件中进行配置下,下面这个选项,表示我们需要得到用户的授权才可以去使用
Privacy - Contacts Usage Description我们可以通过ABAddressBookGetAuthorizationStatus() 这个方法来获取通讯录的状态
这个总共有四个枚举值
kABAuthorizationStatusNotDetermined = 0, // 表示用户还没有决定是否授权你的程序进行访问
kABAuthorizationStatusRestricted, // 表示ios设备上一些许可的配置阻止程序与通讯录进行交互
kABAuthorizationStatusDenied, // 表示用户不允许你访问数据库
kABAuthorizationStatusAuthorized // 表示用户已经授权
然后如果我们想展示界面的话,我们可以进行这样的设置,让点击屏幕的时候去跳出通讯录控制器
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ //1、创建联系人选择控制器 ABPeoplePickerNavigationController * picker = [ABPeoplePickerNavigationController new]; //2、设置代理 这里应该去设置的是peoplePickerDelegate,如果我们去设置的是delegate的话,就是去设置UINavigationController的代理了 picker.peoplePickerDelegate = self; //3、模态视图的弹出 [self presentViewController:picker animated:YES completion:nil]; }跳出的界面如下所示
ABPeoplePickerNavigationControllerDelegate这个协议当中有三个代理方法是需要我们注意的,如下所示
#pragma mark 取消选中联系人的时候调用-(void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker{ NSLog(@"%s",__func__);}
#pragma mark 选中某一个联系人会调用//这里需要注意的是在ios7的时候必须要实现这个方法,否则程序会崩溃-(void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person{ NSLog(@"%s",__func__);}
#pragma mark 选中联系人的某个属性的时候会调用-(void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier{ //property代表的其实就是我们点击进去联系人详情里面的属性的ID NSLog(@"%s",__func__);}
有几点需要注意的是 -(void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person和-(void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
这两个方法如果都实现了,就只会调用didSelectPerson的方法,两个方法我们其实只需要实现一个就可以了。
如果我想要实现点击通讯录中的一个联系人就可以得到它的姓名和电话的话,我们可以在-(void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person这个方法中进行设置,首先我们需要去知道的是ABRecordRef这个是什么类型的,我们可以点进去看到如下所示
/* Base "type" of all "CF objects", and polymorphic functions on them */typedef const CF_BRIDGED_TYPE(id) void * CFTypeRef;这个CFTypeRef其实是和id类型是类似的,可以理解成为把void * 包装CFTypeRef
我们可以调用下面的方法进行获取我们点击的联系人的名字person其实我觉得可以理解成就是一条记录
//1、获取名字 CFStringRef firstName = ABRecordCopyValue(person, kABPersonFirstNameProperty); //转换成OC中的字符串我们需要去做一个桥接 NSString *name = (__bridge NSString *)(firstName); NSLog(@"%@",name); //需要注意的是在Core Foundation中我们需要手动的去释放 CFRelease(firstName);
还有一个方法是直接可以获取姓名的全称的
CFStringRef str = ABRecordCopyCompositeName(person); NSString * name1=(__bridge NSString *)(str); NSLog(@"%@",name1); CFRelease(firstName);
获取电话号码的话,我们一样的可以在didSelectPerson方法中进行设置,我们可以这么做
//获取电话,因为通讯录中的电话肯定不可能只有一个,所以我们要获取的是一个数组类型的 ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty); //获取电话的个数 CFIndex count = ABMultiValueGetCount(phones); //遍历联系人数组 for(CFIndex i=0;i<count;i++) { //获取联系电话的标签也就是联系电话的上面那一栏 NSString * text =(__bridge_transfer NSString *) ABMultiValueCopyLabelAtIndex(phones, i); NSLog(@"%@",text); //获取联系的电话 NSString * value = CFBridgingRelease(ABMultiValueCopyValueAtIndex(phones, i)); NSLog(@"%@",value); } //这里要去释放 CFRelease(phones);
最后再简单的介绍下Core Foundation和 Foundation进行桥接的方式
Core Foundation 和 Foundation进行桥接有三种方式
Foundation框架的对象和Core Foundation对象互相转换
1、(__bridge type) expression) 表示的是如果是Foundation转Core Foundation 就不需要自己去释放,如果是让Foundation暂时的去使用CoreFoundation框架的对象,就需要去释放。
比如说(__bridge CFURLRef _Nonnull)(url) 就是把url对象暂时转换成了Core Foundation的对象
Core Foundation框架的对象转换为Foundation对象
2、(__bridge_transfer Objective-C type)expression) 就是把Core Foundation的框架交给对象的管理权给Foundation框架,也就是说我们不需要再去释放对象了 还有一点需要注意的就是CFBridgingRelease是和transfer的转换是一样的。
最后一种桥接就是将Foundation对象转换成Core Foundation对象
3、(__bridge_retained CF type)expression) 这个就是将Foundation堆中转换成Core Foundation对象。所有权也发生了改变,所以需要我们自己去释放
还有就是如果我们用过在MRC和ARC中让CoreFoundation中的对象转换成ARC的对象的话其实会发现在MRC中我们是不需要去做桥接了的,因为其实已经帮我们做了一个隐式的桥接,但是在ARC中不行因为ARC不能自动处理core Foundation类型。
NSString *string = @"ssss"; CFStringRef str1 = (__bridge_retained CFStringRef)string; NSLog(@"%@",str1);
//关于第一个参数传入的一般来说都是NULL或者而是kCFAllocatorDefault,具体什么含义还没太明白 CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, "sdadad", kCFStringEncodingUTF8); NSString * string = (__bridge_transfer NSString *)str; NSLog(@"%@",string);
- ios-访问通讯录及Core Foundation和Foundation的桥接
- ios-Foundation和Core Foundation
- iOS开发利用桥接(__bridge)简单实现Foundation 和 Core Foundation 相互转换.
- iOS-Core Foundation框架到Foundation桥接的三种方式
- Foundation框架与Core Foundation框架相互之间的桥接
- IOS之Core Foundation框架和Cocoa Foundation框架区别
- IOS之Core Foundation框架和Cocoa Foundation框架区别
- IOS之Core Foundation框架和Cocoa Foundation框架区别
- Foundation和Core Foundation掺杂使用桥接 Toll-Free Bridging
- Foundation和Core Foundation掺杂使用桥接 Toll-Free Bridging
- OC基础---Core Foundation和Cocoa Foundation
- Core Foundation框架和Foundation框架
- iOS内存管理--Core Foundation
- Core Foundation 与 foundation
- Core Foundation与Foundation
- Core Foundation
- [ios]Objective-C 和 Core Foundation 对象相互转换的内存管理总结 【转】
- core foundation framework对象和foundation framework对象的相互转换 ---Toll-Free Bridging
- git stash 命令用法
- PAT 1005. 继续(3n+1)猜想 (25)
- InfoGAN 论文阅读笔记 基本知识总结
- [leetcode]169. Majority Element
- Codeforces 700B 贪心
- ios-访问通讯录及Core Foundation和Foundation的桥接
- 用java在控制台打印日历格式
- 贪心:最优服务次序问题
- Xshell从服务器上传下载
- 真机调试,Could not launch
- 浅析无符号整型和有符号整型
- Tensorflow-gpu Ubuntu16.04 GTX1060 双显卡
- 一只半路出家的程序猴
- Net-snmp总结(一)-snmp的基本概念