在以往的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. boost.asio与boost.log同时使用导致socket不能正常收发数据

    现象: 1. 没有使用boost.log前能正常收发数据 2.加入boost.log后async_connect没有回调 fix过程: 1. gdb调试发现程序block在pthread_timed_ ...

  2. 许愿墙的搭建(基于Apache+php+mysql)

    一.准备部分:CentOS 7  , Linux 文本   各自配置好环境 二. CentOS 7准备如下: yum install httpd -y #安装httpd yum install php ...

  3. MVC 路由介绍

    我们新建一个ASP.NET MVC Web程序的时候,会生成一个Global.asax文件.如下: using System; using System.Collections.Generic; us ...

  4. Error 403--Forbidden

    转自他人:From RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1:10.4.4 403 ForbiddenThe server understood ...

  5. ASP.NET MVC为字段设置多语言显示 [转]

    这段时间一直在忙.NET的项目,今天就写一下关于.NET的文章吧,也很长时间没写过.NET的啦  在使用ASP.NET MVC3 的时候,使用元数据模式可以非常方便地设置每个 字段(或者说属性)以减少 ...

  6. Jenkins构建时报错:No Space left on device

    Jenkins在自动化构建服务的同时也在消耗服务器的磁盘空间,如果构建的项目个数很多,而Jenkins 服务器磁盘空间又不是非常大的话,每隔一段时间磁盘空间就会爆满导致,就会出现磁盘空间不足无法构建的 ...

  7. css个人随笔,适合新手总结整理

    CSS的3种引用方式:1.外部样式表 都是在head标签内使用Link标签来引用的.2.内部样式表 <style type="text/css"> </style ...

  8. Android调用系统照相机

    ndroid调用系统相机实现拍照功能 在实现拍照的功能时遇到了很多问题,搜索了很多资料,尝试了很多办法,终于解决了,下面简要的描述下在开发过程中遇到的问题. 虽然之前看过android开发的书,但是没 ...

  9. Eclipse 常用快捷键

    Ctrl + Shift + L  : 可以查看快捷键方式 Ctrl + 1 : 快速修复 Ctrl + / : 注释当前行 Ctrl + D : 删除当前行 Shift + Enter : 可以在当 ...

  10. struts入门实例

    入门实例 1  .下载struts-2.3.16.3-all  .不摆了.看哈就会下载了. 2  . 解压  后 找到 apps 文件夹. 3.    打开后将 struts2-blank.war   ...