在以往的ios开发中,开发者需要获取用户的通讯录信息的时候,往往要使用AddressBook.frame框架,该框架是纯C语言的API,在开发过程中,还需要开发者手动的管理内存,这对于新进开发者很难理解和掌握。到了IOS9,苹果推出了具有OC语言的API,即Contacts框架,该框架理解简单、易于使用。联系人信息可以短时间获取、创建和修改,而且还不需要去关系对象的释放。

下面我们介绍一下Contacts框架:

在ios8以后,苹果更加注重用户的隐私,因此需要访问用户通讯录的时候,必须给用户发送授权请求,得到用户的确认后,才能进行下一步的操作。如果用户不同意,用户禁止APP获取其通讯录信息,那么这个决定必须被APP采纳,且绝对不能与用户的通讯录信息交互。不仅如此,用户随时可以在设置中更改对APP的授权,因此在任何操作的时候,都需要检查用户的授权状态。

     //1 判断是否授权成功
    if ([CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts] == CNAuthorizationStatusAuthorized) return;//授权成功直接返回
    //2 创建通讯录
    CNContactStore *store = [[CNContactStore alloc] init];
    //3授权
    [store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
        if (granted) {
            NSLog(@"授权成功");
        }else{
            NSLog(@"授权失败");
        }
    }];

authorizationStatusForEntityType:methods这个方法是CNContactStore的类方法,需要一个 CNEntityType 参数,返回值是授权得到的状态CNAuthorizationStatus,一共有四种,分别为:

  1. NotDetermined:表示用户还没有允许或禁止访问通讯录数据库。首次安装的应用软件处于这种状态。
  2. Restricted:不仅应用软件无法访问通讯录数据,就连用户也无法通过设置修改授权状态。该状态是由于其他限制,也就是家长控制(parental control)所导致。
  3. Denied:表示用户不允许访问通讯录数据。只有用户才能够修改该状态。
  4. Authorized:这是每个应用软件期望得到的状态。在该状态下,应用软件可以随意访问通讯录数据库,使用通讯录数据执行操作。

我们其实只需要判断授权状态是否为 CNAuthorizationStatusAuthorized 即可,如果是表示授权状态成功,否则失败,不允许访问通讯录。

CNContactStore (相当于ABAddressBook)类以编程方式展示了联系人数据库,并且提供了许多实现不同任务的方法,例如获取,保存或者更新记录,权限检查和权限请求,很多很多。

CNContact类(相当于ABRecordRef)展示一个单独的联系人记录,但是记住这个类的特性是不可变的。如果你想创建一个新的联系人记录或者更新一个已存在的联系人记录,你必须使用CNMutableContact类。

需要注意的是在于Contacts框架打交道的时候,特别是获取联系人信息时,你应该始终在后台线程中运行这些任务。因为如果一个联系人信息获取任务花去了太多时间而且在主线程运行,那么你的应用有可能无响应,然后最终导致非常糟糕的交互体验。

于此同时在导入联系人信息到APP时,很少用到所有的联系人的属性信息。在所有的Contacts 框架要搜索的数据源中获取所有联系人数据的操作,被证明是一个非常耗资源的进程,所以应该避免检索所以联系人的属性信息,而是只检索需要的一部分属性信息,这个是在Contacts框架提供了的。例如,你可以只是请求名或姓,电话等,这样可以通过排除不需要的那些数据来节约很多资源。

查询联系人代码示例:

 /** 查看联系人 */
- (void)readContact {
    if ([CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts] != CNAuthorizationStatusAuthorized) return;//授权失败直接返回     //创建通讯录对象
    CNContactStore *store = [[CNContactStore alloc] init]; // 创建获取通信录的请求对象
//拿到所有打算获取的属性对应的key(这里仅仅指定需要获取的数据,节约资源)
//我们这里仅仅作为示例,所以获取了所有的信息数据
    NSArray *typeArray = @[CNContactGivenNameKey,CNContactFamilyNameKey,CNContactPhoneNumbersKey,CNContactEmailAddressesKey,CNContactBirthdayKey,CNContactDepartmentNameKey];
    
//创建CNContactFetchRequest对象
    CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:typeArray];     //遍历所有的联系人
    [store enumerateContactsWithFetchRequest:request error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) { //名字
        NSString *firstName = contact.givenName;
//姓氏
        NSString *lastName = contact.familyName;
        
        NSLog(@"%@ -- %@", firstName, lastName);
      
//获取电话信息 
        NSArray *phones = contact.phoneNumbers;
        for (int i = ; i<phones.count; i++) {             CNLabeledValue *phone = phones[i]; //获取电话号码的KEY
            NSString *label = phone.label; //获取电话号码
            CNPhoneNumber *phoneNum = phone.value;
NSString *num = phoneNum.stringValue;
            NSLog(@"name= %@ -- num = %@", label, num);
        } 
    }]; }

插入联系人示例:

 /**
 *  添加联系人
 */
- (IBAction)addContact {
    
    //1、联系人对象:CNContact
    
    //这个对象是用来配置联系人信息的,有可变的CNMutaleContact和CNContact,区别用来读取和创建联系人。CNContact对象中有许多属性,对应联系人的一些信息。
    
    //首先,创建CNMutableContact对象:
    CNMutableContact *contact = [[CNMutableContact alloc]init];
    
    //设置联系人数据
    [self setupContact:contact];
    
    
    //2、创建添加联系人请求:CNSaveRequest
    //CNSaveRequest是用于存储联系人的请求类,通过这个类,我们可以创建批量添加、修改或者删除联系人的请求,例如添加上面我们创建的联系人对象:
    
    //初始化方法
    CNSaveRequest * saveRequest = [[CNSaveRequest alloc] init];
    //添加联系人
    [saveRequest addContact:contact toContainerWithIdentifier:nil];
    
    //3 进行联系人的写入操作:CNContactStore
    //CNContactStore是一个用于存取联系人的上下文桥梁,现在,把我们创建的添加联系人的请求写入:
    CNContactStore * store = [[CNContactStore alloc]init];
    [store executeSaveRequest:saveRequest error:nil];
} /** 设置联系人信息 */
- (void)setupContact:(CNMutableContact *)contact{
    //设置联系人头像:
    contact.imageData = UIImagePNGRepresentation([UIImage imageNamed:@"tour"]);
    
    //设置联系人姓名:
    //设置名字
    contact.givenName = @"xiao";
    //设置姓氏
    contact.familyName = @"zhang";
    
    //设置联系人邮箱(这里需要注意,emailAddresses属性是一个数组,数组中是才CNLabeledValue对象)
    CNLabeledValue *homeEmail = [CNLabeledValue labeledValueWithLabel:CNLabelHome value:@"3242523553@qq.com"];
    CNLabeledValue *workEmail =[CNLabeledValue labeledValueWithLabel:CNLabelWork value:@"324266653@qq.com"];
    contact.emailAddresses = @[homeEmail,workEmail];
    
    //设置联系人电话(和邮箱类似)
    CNLabeledValue *mianPhone = [CNLabeledValue labeledValueWithLabel:CNLabelPhoneNumberMain value:[CNPhoneNumber phoneNumberWithStringValue:@""]];
    CNLabeledValue *homePhone = [CNLabeledValue labeledValueWithLabel:CNLabelPhoneNumberHomeFax value:[CNPhoneNumber phoneNumberWithStringValue:@""]];
    contact.phoneNumbers = @[mianPhone, homePhone];
    
    //设置联系人地址
    CNMutablePostalAddress * homeAdress = [[CNMutablePostalAddress alloc]init];
    homeAdress.street = @"大雁塔";
    homeAdress.city = @"西安";
  homeAdress.state = @"中国";
    homeAdress.postalCode = @"xxxxx";
    contact.postalAddresses = @[[CNLabeledValue labeledValueWithLabel:CNLabelHome value:homeAdress]];
    
    //设置联系人生日
  NSDateComponents * birthday = [[NSDateComponents  alloc] init];
  birthday.day=;
    birthday.month=;
    birthday.year=;
    contact.birthday=birthday;
}

ContactsUI.frame框架

 //打开通讯录
- (IBAction)openContact {
//初始化ContactPickerViewController
    CNContactPickerViewController *pickVc = [[CNContactPickerViewController alloc] init];
    //成为自己的代理
    pickVc.delegate = self;
    //跳转控制器
    [self presentViewController:pickVc animated:YES completion:nil];
} #pragma mark - CNContactPickerDelegate
// 点击cancle按钮时候就会调用
- (void)contactPickerDidCancel:(CNContactPickerViewController *)picker{
    NSLog(@"%s", __func__);
    [picker dismissViewControllerAnimated:YES completion:nil];
} // 选中某一个联系人就会调用
//注意:只要实现了这个方法, 就不会进行下一步操作(进入详情), iOS9的做法是默认返回NO
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContact:(CNContact *)contact{
    NSLog(@"%s", __func__);
    //姓氏
    NSString *firstName = contact.familyName;
//名字
    NSString *lastName = contact.givenName;
    NSLog(@"%@---%@", firstName, lastName);
    //电话信息
    NSArray *phones = contact.phoneNumbers;
    for (CNLabeledValue *phone in phones) {
//电话名称
        NSString *name = phone.label;
//电话号码详情
        CNPhoneNumber *phoneNum = phone.value;
        NSLog(@"name = %@, phoneNum = %@", name, phoneNum.stringValue);
    }
    
} // 选中某一个联系人的某一个属性时就会调用
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperty:(CNContactProperty *)contactProperty{
    NSLog(@"%s", __func__);
}

ios9-通讯录的更多相关文章

  1. 通讯录--(iOS9独有的方法)

    导入库文件   #import <ContactsUI/ContactsUI.h> #pragma mark iOS9 新出的点击通讯录的获取信息的办法 #pragma mark - 先弹 ...

  2. 获取通讯录的信息(关于iOS9.0之后新的框架-ContactFramework)

    转载自:http://my.oschina.net/u/2340880/blog/511995?p={{totalPage}} 一.引言 在以前iOS开发中,涉及联系人相关的编程,代码都非常繁琐,并且 ...

  3. iOS中通讯录的开发

    通讯录开发主要是获取用户手机中的联系人,进而可以在应用中添加好友 一 .如何访问通讯录 (1)在iOS9之前,有两个框架可以访问用户的通讯录 AddressBookUI.framework: 提供了联 ...

  4. iOS通讯录整合,兼容iOS789写法,附demo

    苹果的通讯录功能在iOS7,iOS8,iOS9 都有着一定的不同,iOS7和8用的是 <AddressBookUI/AddressBookUI.h> ,但是两个系统版本的代理方法有一些变化 ...

  5. iOS开发——高级篇——通讯录

    一.简介 1.如何访问用户的通讯录1)在iOS9之前有2个框架可以访问用户的通讯录AddressBookUI.framework提供了联系人列表界面.联系人详情界面.添加联系人界面等一般用于选择联系人 ...

  6. iOS8通讯录之联系人增删查,多号码增删操作

    #import <AddressBook/AddressBook.h> #pragma mark 删除一个号码 - (void)deleteLocalMarkSuccess:(void(^ ...

  7. ios开发 通讯录

    一.通信录开发 通信录开发主要是获取用户手机中的联系人 通过获取用户的通信录,可以在应用中添加好友等 二.如何访问用户的通讯录 在iOS9之前,有2个框架可以访问用户的通讯录 目前需要适配iOS8,所 ...

  8. IOS9中联系人对象的使用及增删改查操作的函数封装

    之前克服重重困难把IOS9中新的类联系人搞明白了,现在把增删改查封装成了函数,如下: // // ViewController.m // IOS9中联系人CNContact的使用 // // Crea ...

  9. iOS7,iOS8和iOS9的区别

    iOS7,iOS8和iOS9的区别:iOS7.0 1.iOS 7是iOS面世以来在用户界面上做出改变最大的一个操作系统.iOS 7抛弃了以往的拟物化设计,而采用了扁平化设计. 苹果在重新思考 iOS ...

  10. iOS开发学习-类似微信聊天消息中的电话号码点击保存到通讯录中的功能

    类似微信聊天消息中的电话号码点击保存到通讯录中的功能,ABAddress的实现在iOS9中是不能正常使用的,点击完成后,手机会非常的卡,iOS9之后需要使用Contact新提供的方法来实现该功能.快捷 ...

随机推荐

  1. 深入Docker

    深入Docker 作者:ramanallamilli 随着持续交付等新型开发方法的兴起,工程师再也不会凡事靠运气,希望提交代码上去后,它能在未知环境正常运行.我们可以看到业界这样的转变——开发,质量保 ...

  2. MongoDB 驱动以及分布式集群读取优先级设置

    本文主要介绍使用MongoDB C驱动读取分布式MongoDB集群时遇到的坑,主要在读取优先级和匹配tag上:同时简单介绍Python驱动.Node.js驱动.Mongoose驱动如何使用读取优先级和 ...

  3. Kettle6.0安装及问题总结-白痴教程

    1.安装JDK 配置java环境变量 2.安装KETTLE: 官方下载地址:http://community.pentaho.com/projects/data-integration/ 下载完后,解 ...

  4. CentOS搭建VPN

    安装ppp #yum install ppp 安装pptpd 配置软件源,修改/etc/yum.repos.d/Doylenet.repo,如果系统没有该文件则创建 #vim /etc/yum.rep ...

  5. HTTP_REFERER

    .htaccess可以禁止某个来源(referer)的访问,当某个网站对你的网站图片或CSS等文件直接引用的时候,禁止其访问是避免更大损失的关键. RewriteEngine onRewriteCon ...

  6. 修改Linux默认启动级别或模式的方法

    冲动的惩罚: 海阔天空: 在linux系统的7种启动级别,默认为X-Window,类似于Windows的窗口模式. 如何修改或变更linux的默认启动级别或模式呢? 以root身份进入Linux,修改 ...

  7. FTP Proxy Server

    本文将在Linux环境下实现一个简单的FTP代理服务器,主要内容涉及FTP主动/被动模式和简单的Socket编程. 1. 主动模式和被动模式 FTP有两种模式,即主动模式(Active Mode)和被 ...

  8. VS 自动添加注释

    现在大多数公司都规定程序员在程序文件的头部加上版权信息,这样每个人写的文件都可以区分开来,如果某个文件出现问题就可以快速的找到文件的创建人,用最短的时间来解决问题,常常是以下格式: //======= ...

  9. OC基础--结构体 枚举做类成员属性

    结构体  枚举作类的成员属性: 定义一个学生类 性别 -- 枚举 生日 入学日期  毕业日期  --  结构体 代码示例: 声明文件 Student.h: #import <Foundation ...

  10. MSChart绘图控件中折线图和柱形图画法

    首先在前台拖入一个名为chart1的MSChart控件 //折线图 string strLegend = "Legend1"; Legend lg = new Legend(str ...