美文网首页iOS Developer
重点 (二十九) : 通讯录

重点 (二十九) : 通讯录

作者: JonesCxy | 来源:发表于2016-10-18 09:20 被阅读200次

    如何访问用户的通讯录

    在iOS中,有2个框架可以访问用户的通讯录

    AddressBookUI.framework

    提供了联系人列表界面、联系人详情界面、添加联系人界面等

    一般用于选择联系人

    AddressBook.framework

    纯C语言的API,仅仅是获得联系人数据

    没有提供UI界面展示,需要自己搭建联系人展示界面

    里面的数据类型大部分基于Core Foundation框架,使用起来极其蛋疼

    从iOS6开始,需要得到用户的授权才能访问通讯录,因此在使用之前,需要检查用户是否已经授权

    获得通讯录的授权状态:ABAddressBookGetAuthorizationStatus()

    授权状态

    kABAuthorizationStatusNotDetermined

    用户还没有决定是否授权你的程序进行访问

    kABAuthorizationStatusRestricted

    iOS设备上的家长控制或其它一些许可配置阻止程序与通讯录数据库进行交互

    kABAuthorizationStatusDenied

    用户明确的拒绝了你的程序对通讯录的访问

    kABAuthorizationStatusAuthorized

    用户已经授权给你的程序对通讯录进行访问

    申请访问通讯录

    实例化通讯录对象

    ABAddressBookRefaddressBook = ABAddressBookCreateWithOptions(NULL, NULL);

    ABAddressBookRequestAccessWithCompletion(addressBook, ^(boolgranted, CFErrorReferror) {

    if (granted)
    

    {

        NSLog(@"授权成功!");
    
    } else {
    
        NSLog(@"授权失败!");
    
    }
    

    });

    CFRelease(addressBook);

    提示:申请通讯录访问授权的代码,通常放在AppDelegate中

    联系人属性定义

    所有的属性常量值都定义在了ABPerson.h头文件中

    联系人属性包括以下类型:

    简单属性:姓、名等

    多重属性:电话号码、电子邮件等

    组合属性:地址等

    注意:使用ABRecordCopyValue可以从一条Person记录中获取到对应的记录,但是后续处理则需要根据记录的具体类型加以区分

    简单属性

    一个联系人就是一个ABRecordRef,每个联系人都有自己的属性,比如名字、电话、邮件等

    使用ABRecordCopyValue函数可以从ABRecordRef中获得联系人的简单属性(例如:一个字符串)

    ABRecordCopyValue函数接收2个参数

    第1个参数是ABRecordRef实例

    第2个参数是属性关键字,定义在ABPerson.h中

    ABPersonCopyLocalizedPropertyName函数可以根据指定的关键字获取对应的标签文本

    获得所有的联系人数据

    获取所有联系人记录

    CFArrayRefarray = ABAddressBookCopyArrayOfAllPeople(addressBook);

    NSInteger count = CFArrayGetCount(array);

    for (NSInteger i =0; i < count; ++i) {

    取出一条记录
    
    ABRecordRef person =
    

    CFArrayGetValueAtIndex(array, i);

    取出个人记录中的详细信息
    
    名
    
    CFStringRef firstNameLabel =
    

    ABPersonCopyLocalizedPropertyName(kABPersonFirstNameProperty);

    CFStringRef firstName =
    

    ABRecordCopyValue(person, kABPersonFirstNameProperty);

    CFStringRef
    

    lastNameLabel = ABPersonCopyLocalizedPropertyName(kABPersonLastNameProperty);

    姓
    
    CFStringRef lastName = ABRecordCopyValue(person,
    

    kABPersonLastNameProperty);

    NSLog(@"%@ %@ - %@ %@", lastNameLabel,
    

    lastName, firstNameLabel, firstName);

    }

    CoreFoundation 与 Foundation之间的桥接

    1. 获取通讯录引用

    ABAddressBookRefaddressBook = ABAddressBookCreateWithOptions(NULL, nil);

    1. 获取所有联系人记录

    NSArray*array = (__bridge NSArray *)(ABAddressBookCopyArrayOfAllPeople(addressBook));

    for (NSInteger i = 0;
    i < array.count; i++) {

        取出一条记录
    
        ABRecordRef
    

    person = (__bridge ABRecordRef)(array[i]);

        取出个人记录中的详细信息
    
        NSString *firstNameLabel
    

    = (__bridge NSString*)(ABPersonCopyLocalizedPropertyName(kABPersonFirstNameProperty));

    NSString *firstName = (__bridge NSString*)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
    
    NSString *lastNameLabel
    

    = (__bridge NSString*)(ABPersonCopyLocalizedPropertyName(kABPersonLastNameProperty));

    NSString *lastName = (__bridge NSString*)(ABRecordCopyValue(person, kABPersonLastNameProperty));
    
    NSLog(@"%@ %@ - %@ %@", lastNameLabel,
    

    lastName, firstNameLabel, firstName);

    }

    CFRelease(addressBook);

    结论:转换看起来很美~~~

    多重属性

    联系人的有些属性值就没这么简单,一个属性可能会包含多个值

    比如邮箱,分为工作邮箱、住宅邮箱、其他邮箱等

    比如电话,分为工作电话、住宅电话、其他电话等

    如果是复杂属性,那么ABRecordCopyValue函数返回的就是ABMultiValueRef类型的数据,例如邮箱或者电话

    取电话号码

    ABMultiValueRefphones = ABRecordCopyValue(person, kABPersonPhoneProperty);

    取记录数量

    NSInteger phoneCount =ABMultiValueGetCount(phones);

    遍历所有的电话号码

    for (NSInteger i = 0;
    i < phoneCount; i++) {

    获取复杂属性的方法

    电话标签

    CFStringRefphoneLabel = ABMultiValueCopyLabelAtIndex(phones, i);

    本地化电话标签

    CFStringRef
    phoneLocalLabel = ABAddressBookCopyLocalizedLabel(phoneLabel);

    电话号码

    CFStringRef phoneNumber
    = ABMultiValueCopyValueAtIndex(phones, i);

    添加联系人的步骤

    添加联系人的步骤

    通过ABPersonCreate函数创建一个新的联系人(返回ABRecordRef)

    通过ABRecordSetValue函数设置联系人的属性

    通过ABAddressBookAddRecord函数将联系人添加到通讯录数据库中

    通过ABAddressBookSave函数保存刚才所作的修改

    可以通过ABAddressBookHasUnsavedChanges函数判断是否有未保存的修改

    当决定是否更改通讯录数据库后,你可以分别使用 AbAddressBookSave 或 ABAddressBookRevert 方式来保存或放弃更改

    添加群组的步骤

    添加群组的步骤大体和添加联系人一致

    通过ABPersonCreate函数创建一个新的组(返回ABRecordRef)

    通过ABRecordSetValue函数设置组名

    通过ABAddressBookAddRecord函数将组添加到通讯录数据库中

    通过ABAddressBookSave函数保存刚才所作的修改

    操作联系人的头像

    想操作联系人的头像,有以下函数

    BPersonHasImageData

    判断通讯录中的联系人是否有图片

    ABPersonCopyImageData

    取得图片数据(假如有的话)

    ABPersonSetImageData

    设置联系人的图片数据

    *******************笔记**********************


    一. 通讯录获取

    1. 通讯录应用场景

    2. 最常见的是一些即时通讯APP, 关联联系人;

    1. 通讯录获取方案

    1.AddressBookUI.framework 框架

    提供了联系人列表界面、联系人详情界面、添加联系人界面等

    一般用于选择联系人

    2.AddressBook.framework 框架

    纯C语言的API,仅仅是获得联系人数据

    没有提供UI界面展示,需要自己搭建联系人展示界面

    里面的数据类型大部分基于Core Foundation框架,使用起来极其蛋疼

    3.ContactsUI.framework (iOS9.0最新框架)

    方案1/方案2 的替代品

    4.第三方框架
    RHAddressBook

    对AddressBook.framework框架的封装

    1. 获取通讯录-AddressBookUI

    2. 实现步骤

    1.创建选择联系人的控制器

    2.设置代理(用来接收用户选择的联系人信息)

    3.弹出联系人控制器

    4.实现代理

    5.在对应的代理方法中获取联系人信息

    1. 具体代码实现

    1.创建选择联系人的控制器

    ABPeoplePickerNavigationController
    *ppnc = [[ABPeoplePickerNavigationController alloc] init];

    2.设置代理(用来接收用户选择的联系人信息)

    ppnc.peoplePickerDelegate
    = self;

    3.弹出联系人控制器

    [self presentViewController:ppnc animated:YES completion:nil];

    4.实现代理

    1. 选中某个联系人时调用
    • (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController
      *)peoplePicker didSelectPerson:(ABRecordRef)person

    {

    }

    1. 选中某个联系人某个属性时调用
    • (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController
      *)peoplePicker didSelectPerson:(ABRecordRef)person
      property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier

    {

    }

    1. 点击了取消按钮会执行该方法
    • (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController
      *)peoplePicker

    {

    }

    5.在对应的代理方法中获取联系人信息

    1. 获取选中联系人的姓名(姓lastname和名firstname)

    CFStringRef
    firstname = ABRecordCopyValue(person, kABPersonFirstNameProperty);

    CFStringRef
    lastname = ABRecordCopyValue(person, kABPersonLastNameProperty);

    NSString
    *firstName = (__bridge_transfer NSString
    *)(firstname);

    NSString
    *lastName = (__bridge_transfer NSString
    *)(lastname);

    NSLog(@"%@ %@", firstName, lastName);

    1. 获取联系人的电话号码

    ABMultiValueRef
    phones = ABRecordCopyValue(person, kABPersonPhoneProperty);

    CFIndex
    count = ABMultiValueGetCount(phones);

    for (CFIndex i = 0; i < count; i++) {

    NSString *phoneLabel = (__bridge_transfer
    NSString *)ABMultiValueCopyLabelAtIndex(phones, i);

    NSString *phoneValue = (__bridge_transfer
    NSString *)ABMultiValueCopyValueAtIndex(phones, i);

    NSLog(@"label : %@ value : %@",
    phoneLabel, phoneValue);

    }

    1. 释放不再使用的对象

    CFRelease(phones);

    1. 获取通讯录-AddressBook

    2. 实现步骤

    1.请求授权

    2.判断授权状态, 如果已授权, 则继续; 未授权, 则提示用户, 并返回;

    3.创建通讯录对象

    4.从通信录对象中, 获取所有的联系人

    5.遍历所有的联系人

    6.释放不再使用的对象

    1. 代码实现

    1.请求授权

    1.获取授权的状态

    ABAuthorizationStatus
    status = ABAddressBookGetAuthorizationStatus();

    2.判断授权状态,如果是未决定状态,才需要请求

    if (status == kABAuthorizationStatusNotDetermined)
    {

    2.1.创建通信录对象
    

    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);

    2.2.请求授权
    

    ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {

      if (granted) {
    
            NSLog(@"授权成功");
    
    
      } else {
    
            NSLog(@"授权失败");
    
    
      }
    

    });

    }

    2.判断授权状态, 如果已授权, 则继续; 未授权, 则提示用户, 并返回;

    1.获取授权的状态

    ABAuthorizationStatus
    status = ABAddressBookGetAuthorizationStatus();

    2.如果用户已经授权

    if (status != kABAuthorizationStatusAuthorized)return;

    3.创建通讯录对象

    ABAddressBookRef
    addressBook = ABAddressBookCreateWithOptions(NULL,
    NULL);

    4.从通信录对象中, 获取所有的联系人

    CFArrayRef
    peopleArray = ABAddressBookCopyArrayOfAllPeople(addressBook);

    5.遍历所有的联系人

    5.遍历所有的联系人(每一个联系人都是一条记录)

    CFIndex
    peopleCount = CFArrayGetCount(peopleArray);

    for (CFIndex i = 0; i < peopleCount; i++) {

    6.获取到联系人
    

    ABRecordRef person = CFArrayGetValueAtIndex(peopleArray, i);

    7.获取姓名
    

    NSString *lastname = (__bridge_transfer
    NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);

    NSString *firstName = (__bridge_transfer
    NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);

    NSLog(@"%@ %@", lastname,
    firstName);

    }

    6.释放不再使用的对象

    CFRelease(peopleArray);

    CFRelease(addressBook);

    1. 获取通讯录-第三方框架RHAddressBook

    2. 实现步骤

    1.集成框架

    2.使用框架获取所有联系人信息

    1. 具体实现

    1.集成框架

    1. 将整个工程拖入项目
    1. 添加工程依赖

    Build
    Phases -> Target Dependencies -> +

    1. 添加链接项

    Build
    Settings -> Other Linker Flags -> -ObjC -all_load

    1. 导入框架头文件

    import <RHAddressBook/AddressBoook.h>

    2.使用框架获取所有联系人信息

    请求授权

    1. 获取授权状态

    RHAuthorizationStatus
    status = [RHAddressBook authorizationStatus];

    if (status == RHAuthorizationStatusNotDetermined)

    {

    2. 创建通讯录对象
    

    RHAddressBook *addressBook = [[RHAddressBook alloc] init];

    3. 请求授权
    

    [addressBook requestAuthorizationWithCompletion:^(bool granted, NSError *error) {

      if (granted)
    
    
      {
    
            NSLog(@"授权成功!");
    
    
      }
    
    
      else
    
    
      {
    
            NSLog(@"授权失败");
    
    
      }
    

    }];

    }

    获取联系人信息

    1. 判断当前授权状态

    RHAuthorizationStatus
    status = [RHAddressBook authorizationStatus];

    if (status != RHAuthorizationStatusAuthorized) {

    return;
    

    }

    1. 创建通讯录对象

    RHAddressBook
    *addressBook = [[RHAddressBook alloc] init];

    1. 获取所有联系人

    NSArray
    *peoples = addressBook.people;

    1. 遍历所有联系人

    for (RHPerson *person in
    peoples)

    {

    4.1 获取联系人姓名
    

    NSString *firstName = person.firstName;

    NSString *lastName = person.lastName;

    NSLog(@"%@---%@",
    firstName, lastName);

    4.2 获取联系人电话
    

    RHMultiStringValue *mv = person.phoneNumbers;

    for (int
    i = 0; i < mv.count; i ++)

    {

        4.2.1 获取电话标签
    
    
      NSString *label = [mv labelAtIndex:i];
    
    
     
    
        4.2.2 获取电话号码
    
    
      NSString *phone = [mv valueAtIndex:i];
    
    
      NSLog(@"%@--%@",
    

    label, phone);

    }

    }

    相关文章

      网友评论

        本文标题:重点 (二十九) : 通讯录

        本文链接:https://www.haomeiwen.com/subject/bwgzyttx.html