通讯录访问

本文介绍了iOS中访问通讯录的方法,包括使用Contacts框架获取、修改联系人信息,以及通过ContactsUI框架展示系统通讯录。重点讲述了Contacts的CNContactStore、CNContact、CNMutableContact类以及ContactsUI的CNContactPickerViewController和CNContactViewController的使用。
摘要由CSDN通过智能技术生成

前言:

QQ通讯录、微信电话本会使用iOS的通讯录,iOS中的通讯录是存储在数据库中的,由于iOS的权限设计,开发人员是不允许直接访问通讯录数据库的。在iOS中带有一个Contacts应用程序来管理联系人,但是有些时候我们希望自己的应用能够访问或者修改这些信息,本节我们就来看一下如何访问通讯录中的数据。

iOS关于通讯录的开发有两种,一种是直接调用系统的通讯录界面,根据回调信息处理数据,另一种是直接获取系统的通讯录,完全自定义UI,并且可以通过官方给我们提供的接口进行读写。在iOS9前后,通讯录的访问方式有了重大更新,以前使用的框架都被弃用,本文主要对新的框架的使用做介绍,被弃用的框架会在后面的拓展部分做一下简单说明。

下面是对通讯录访问的几个框架的简单说明:
这里写图片描述


1. Contacts

iOS9中,苹果介绍了新的Contacts。允许用户使用Objective-C的API和设备的通讯录进行交互,同样适用于Swift语言。比起之前通过AddressBook来读取联系人信息来说,这是一个巨大的进步。因为AddressBook没有Objective-C的API,非常难用,用Swift写的时候更是痛苦。通常情况下,AddressBook不容易理解和掌握,对于新手来说更甚。这所有的一切都成为了历史,新的Contacts框架更加容易理解和使用,完全可以即刻获取通讯录,并可以进行创建和更新操作,与之相关的开发过程也可以被戏剧般地缩短,能够迅速地完成对通讯录的变更和修改。

通讯录的主要数据来源应该存在于设备中的数据库。但是,应用需要通讯录数据时,Contacts框架不会只从数据库中查找。事实上应用软件还会从其他地方查找,像iCloud账号(如果你创建并连接了该账号的话),向应用软件统一返回来自于不同数据源的通讯录数据。这项功能非常有用,因为你不用对设备以外的数据库做单独查询以获得通讯录信息,而是能够按自己的意愿管理,一劳永逸。 使用Contacts 从Framework中返回的联系人是统一的,这意味着,如果你有从不同的数据源来的相同联系人数据,他们会自动合并,无需手动进行合并的操作。

Contacts框架含有许多特定用途的类,所有这些类各司其职。下面我们来看一下Contacts框架中几个常用的类:

  • CNContactStore类,是用得最多的一个类,CNContactStore从代码层面代表通讯录数据库,提供不同方法执行相关操作。像获取数据,保存和更新记录,授权查询和授权请求等。
  • CNContact类代表通讯录中单独一条记录,但是CNContact一旦在内存中被实例化就是不可变的了。如果你想要创建一条新的,或者对现存的记录做更新的话,那就必须使用CNMutableContact类。
  • CNContactFetchRequest类,获取通讯录中通讯信息的请求对象,向应用软件导入通讯录的时候,很少会需要所有的信息。将Contacts框架查询到的所有信息悉数获取的做法会导致进程吞噬资源,除非真得需要使用所有数据,否则应该避免这样的操作。我们可以在初始化CNContactFetchRequest时设置请求的具体参数。例如,你可以获取First Name和Last Name,还可以获取通讯住址,以及电话号码。不动那些不需要的数据,节省了很多资源。

下面是使用Contacts框架的而基本步骤:

  • 集成Contacts框架并导入头文件
  • 创建通信录对象CNContactStore
  • 获取授权状态 并判断授权状态,如果不是已经授权,则直接返回
  • 创建获取通信录的请求对象CNContactFetchRequest
  • 通过请求遍历通信录 获取所有的联系人
  • 获取联系人信息
    这里写图片描述
1.1 获取系统通讯录联系人列表

示例代码:

#import "ViewController.h"
#import <Contacts/Contacts.h>

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}

// 获取所有的联系人信息
- (IBAction)getContact:(id)sender{


    // 1.创建通信录对象CNContactStore,CNContactStore是一个用来读取和保存联系人的新的类。可以用来进行展示和保存联系人群组操作
    CNContactStore *contactStore = [[CNContactStore alloc] init];

    // 2.获取授权状态并判断授权状态,如果不是已经授权,则直接返回
    [contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
        // 完成授权后就不会再次请求,避免了重复的UI操作

        CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
        if (status != CNAuthorizationStatusAuthorized) return;

        // 3.创建获取通信录的请求对象。当我们有了这个联系人数据库的引用后,我们需要创建一个指定条件的请求,通过这个请求去获取某些结果。创建一个CNContactFetchRequest,我们可以通过设置contactkeys的数组,来获取我们需要的结果。
        // 3.1 拿到所有打算获取的属性对应的key
        NSArray *keys = @[CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey];
        // 3.2 创建CNContactFetchRequest对象
        CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:keys];

        // 4.通过请求遍历通信录 获取所有的联系人,从CNContactStore 中遍历所有符合我们需求的联系人。这个request 没有加任何的条件,所以会返回全部的联系人,包含我们需要的 keys。我们把每一条记录都逐个保存到一个数组中,返回。
        [contactStore enumerateContactsWithFetchRequest:request error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {

            // 5.获取联系人信息
            // 获取联系人的姓名
            NSString *lastname = contact.familyName;
            NSString *firstname = contact.givenName;
            NSLog(@"%@ %@", lastname, firstname);

            // 获取联系人的电话号码
            NSArray *phoneNums = contact.phoneNumbers;
            for (CNLabeledValue *labeledValue in phoneNums) {
                // 2.1.获取电话号码的KEY
                NSString *phoneLabel = labeledValue.label;

                // 2.2.获取电话号码
                CNPhoneNumber *phoneNumer = labeledValue.value;
                NSString *phoneValue = phoneNumer.stringValue;

                NSLog(@"%@ %@", phoneLabel, phoneValue);
            }
        }];
    }];
}
@end

注意:使用Contacts框架时,特别是在获取通讯录信息的时候,应该在后台线程中执行这些操作。如果获取操作在主线程执行,耗费过多时间的话,那么应用软件会失去响应,最终导致不良的用户体验。

1.2 获取指定的联系人

除了上面我们获取通讯录中所有的联系人之外,我们也可以通过指定谓词的方式来获取想要的联系人信息,Predicate:对于返回的结果来说,NSPredicate对象实际上起到了过滤的作用。这里要强调的重点是,只有CNContact类的谓词(CNContact Predicates)才可以,自己创建的普通谓词不行。在CNContact类所支持的诸多谓词函数里,我们要用到一个叫做predicateForContactsMatchingName的函数。实现通过谓词检索联系人的关键方法就是unifiedContactsMatchingPredicate: keysToFetch:error:方法。下面,我们来指定联系人姓名获取对应的联系人信息。

示例代码:

#import "ViewController.h"
#import <Contacts/Contacts.h>

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}

// 通过谓词获取部分通讯录信息
- (IBAction)getContactWithPredicate:(id)sender {


    // 0.生成谓词作为请求参数
    NSPredicate *predicate = [CNContact predicateForContactsMatchingName:@“"];


    // 1.创建通信录对象CNContactStore
    CNContactStore *contactStore = [[CNContactStore alloc] init];

    // 2.获取授权状态并判断授权状态
    [contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {

        CNAuthorizatio
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值