关于通讯录

通讯录获取

通讯录简介

  • 通讯录应用场景

    • 最常见的是一些即时通讯APP, 关联联系人;
  • 通讯录获取方案

    1. AddressBookUI.framework 框架

      提供了联系人列表界面、联系人详情界面、添加联系人界面等,一般用于选择联系人

    2. AddressBook.framework 框架

      • 纯C语言的API,仅仅是获得联系人数据
      • 没有提供UI界面展示,需要自己搭建联系人展示界面
      • 里面的数据类型大部分基于Core Foundation框架,使用起来极其蛋疼
      • 从iOS6开始,需要得到用户的授权才能访问通讯录,因此在使用之前,需要检查用户是否已经授权
    3. 第三方框架 RHAddressBook

      对AddressBook.framework框架的封装

    4. iOS9.0最新通讯录获取框架 ContactsUI.framework: 方案1的替代品

      特点: 面向对象, 使用简单. 有界面.

      Contacts.framework: 方案2的替代品

      特点: 面向对象, 使用简单. 无界面.

  • 获取通讯录-AddressBookUI

实现步骤

  1. 创建选择联系人的控制器
  2. 设置代理(用来接收用户选择的联系人信息)
  3. 弹出联系人控制器
  4. 实现代理
  5. 在对应的代理方法中获取联系人信息

由于AddressBookUI已经是过期的,swift3.0不再支持,所以只能用OC描述上述步骤

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

@interface ViewController ()<ABPeoplePickerNavigationControllerDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

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

    vc.peoplePickerDelegate = self;

    [self presentViewController:vc animated:YES completion:nil];
}

//当通讯录退出时调用
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker {

    NSLog(@"%s",__func__);
}


//选中联系人通讯录就退出
- (void)peoplePjiezickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person {

    //ABRecordRef 表示一个联系人,一条记录
    //从记录终取值,需要借助ABRecordCopyValue
    //联系人里的记录分为2个类型:
    //简单属性:如姓名
    //复杂属性:如联系方式、邮件等,一般用 “标签” + “值”

    NSLog(@"%s",__func__);

    NSLog(@"选中联系人");
    CFStringRef firstName = ABRecordCopyValue(person, kABPersonFirstNameProperty);
    CFStringRef lastName = ABRecordCopyValue(person, kABPersonLastNameProperty);

    NSString *fir = CFBridgingRelease(firstName);
    NSString *las = CFBridgingRelease(lastName);

    NSLog(@"%@---%@", fir, las);


    ABMultiValueRef multi = ABRecordCopyValue(person, kABPersonPhoneProperty);
    CFIndex count = ABMultiValueGetCount(multi);
    for (int i = 0; i  < count; i++) {
        NSString *label = (__bridge_transfer NSString *)ABMultiValueCopyLabelAtIndex(multi, i);
        NSString *phone =(__bridge_transfer NSString *)  ABMultiValueCopyValueAtIndex(multi, i);
        NSLog(@"%@---%@", label, phone);
    }
}

//选中联系人的某个属性再退出,要使用该方法,不能与上面的方法并存
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier {

    NSLog(@"%s",__func__);
}


@end
  • 获取通讯录-AddressBook

实现步骤

  1. 请求授权
  2. 判断授权状态, 如果已授权, 则继续; 未授权, 则提示用户, 并返回;
  3. 创建通讯录对象
  4. 从通信录对象中, 获取所有的联系人
  5. 遍历所有的联系人
  6. 释放不再使用的对象

info.plist添加权限:Privacy - Contacts Usage Description

由于AddressBook也已经是过期的,swift3.0不再支持,所以只能用OC描述上述步骤

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

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [self getAuthor];



}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    /*
     kABAuthorizationStatusNotDetermined = 0,
     kABAuthorizationStatusRestricted,
     kABAuthorizationStatusDenied,
     kABAuthorizationStatusAuthorized
     */
    // 0. 判断当前的授权状态
    if (ABAddressBookGetAuthorizationStatus() != kABAuthorizationStatusAuthorized) return;

    // 1. 创建通讯录对象
    ABAddressBookRef bookRef = ABAddressBookCreate();

    // 2. 获取通讯录中所有的联系人
    CFArrayRef arrayRef = ABAddressBookCopyArrayOfAllPeople(bookRef);

    // 3. 遍历所有联系人
    CFIndex count = CFArrayGetCount(arrayRef);
    for (int i = 0; i < count; i++) {
        ABRecordRef record = CFArrayGetValueAtIndex(arrayRef, i);

        // 获取姓名
        NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(record, kABPersonFirstNameProperty);
        NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(record, kABPersonLastNameProperty);
        NSLog(@"%@---%@", firstName, lastName);

        // 获取电话号码
        ABMultiValueRef multiValue = ABRecordCopyValue(record, kABPersonPhoneProperty);
        CFIndex count = ABMultiValueGetCount(multiValue);
        for (int i = 0; i < count; i ++) {
            NSString *label = (__bridge_transfer NSString *)ABMultiValueCopyLabelAtIndex(multiValue, i);
            NSString *phone = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(multiValue, i);
            NSLog(@"%@---%@", label, phone);

        }
        CFRelease(multiValue);
    }

    // 释放对象
    CFRelease(bookRef);
    CFRelease(arrayRef);
}

- (void)getAuthor
{
    // 判断当前的授权状态是否是用户还未选择的状态
    if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
        ABAddressBookRef bookRef = ABAddressBookCreate();
        ABAddressBookRequestAccessWithCompletion(bookRef, ^(bool granted, CFErrorRef error) {
            if (granted) {
                NSLog(@"授权成功!");
            }
            else
            {
                NSLog(@"授权失败!");
            }
        });
    }
}

@end

ContactsUI.framework的使用

使用步骤

  • 导入框架ContactsUI
  • 创建选择联系人界面 CNContactPickerViewController
  • 设置代理
  • 弹出选择联系人界面的控制器
  • 获取联系人
    • 实现对应的代理方法
    • 如果实现了选择联系人的代理方法,则无法进入详情界面
    • 获取联系人的姓名
    • 获取联系人的电话号码
import UIKit
import ContactsUI

class ViewController: UIViewController {

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

        let vc = CNContactPickerViewController()

        vc.delegate = self

        present(vc, animated: true, completion: nil)
    }
}

extension ViewController: CNContactPickerDelegate {

    //1.退出联系人界面调用
    func contactPickerDidCancel(_ picker: CNContactPickerViewController) {
        print("通讯录界面退出")
    }

    //以下2,3,4,5方法不能同时使用

    //2.当选中某个联系人调用
    func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) {
        print("选中了联系人:" + contact.givenName + " " + contact.middleName + " " + contact.familyName)

        for phoneNumber in contact.phoneNumbers {
            print("\(phoneNumber.label!) : \(phoneNumber.value.stringValue)")
        }
    }


    //3.选择多个联系人调用
    func contactPicker(_ picker: CNContactPickerViewController, didSelect contacts: [CNContact]) {
        for contact in contacts {
            print("选中了联系人:" + contact.givenName + " " + contact.middleName + " " + contact.familyName)

            for phoneNumber in contact.phoneNumbers {
                print("\(phoneNumber.label!) : \(phoneNumber.value.stringValue)")
            }
        }
    }


    //4.当选中某个联系人的某个属性调用 不能和2,3共同存在
    func contactPicker(_ picker: CNContactPickerViewController, didSelect contactProperty: CNContactProperty) {

        print("选中了联系人\(contactProperty.contact.familyName)的某个属性:\(contactProperty.key),其信息为:\(contactProperty.value)")

    }

    //5.当选中某个联系人的多个属性调用
    func contactPicker(_ picker: CNContactPickerViewController, didSelectContactProperties contactProperties: [CNContactProperty]) {

        for contactProperty in contactProperties {

            print("选中了联系人\(contactProperty.contact.familyName)的某个属性:\(contactProperty.key),其信息为:\(contactProperty.value)")
        }
    }
}

iOS9.0之后的做法

Contacts.framework的使用

  • 请求授权
    • 获取授权状态
    • 判断是否是未决定状态
    • 请求授权
  • 获取联系人
    • 获取授权状态
    • 判断是否是已经授权状态
    • 创建联系人仓库
    • 创建联系人的请求对象
    • 获取用户的姓名
    • 获取电话号码

info.plist加入Privacy - Contacts Usage Description权限

import UIKit
import Contacts

class ViewController: UIViewController {

    //请求联系人仓库
    //let store = CNContactStore()

    lazy var store:CNContactStore? = {

        if #available(iOS 9.0, *)
        {
            return CNContactStore()
        } else {
            return nil
        }

    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        let status = CNContactStore.authorizationStatus(for: .contacts)

        if status == .notDetermined {

           //请求授权
            store?.requestAccess(for: .contacts, completionHandler: { (granted:Bool, e:Error?) in

                if granted {
                    print("授权成功")
                } else {
                    print("授权失败")
                }

            })
        }

    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

        //创建请求对象
        let request = CNContactFetchRequest(keysToFetch: [CNContactFamilyNameKey as CNKeyDescriptor,CNContactPhoneNumbersKey as CNKeyDescriptor])

        //遍历所有联系人信息
        do{
            try store?.enumerateContacts(with: request) { (contact:CNContact, stop:UnsafeMutablePointer<ObjCBool>) in
                print(contact.familyName)
                for number in contact.phoneNumbers {
                    print(number.label! + ":" + number.value.stringValue)
                }

                //*stop = YES(OC)
                stop.initialize(to: true)
            }
        } catch {
            print(error)
        }

    }
}

results matching ""

    No results matching ""