美文网首页
IOS 通讯录 访问和使用

IOS 通讯录 访问和使用

作者: 越天高 | 来源:发表于2020-06-02 17:22 被阅读0次

01.通讯录简介

通讯录应用场景

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

通讯录获取方案

  1. AddressBookUI.framework 框架

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

  1. AddressBook.framework 框架

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

  1. 第三方框架 RHAddressBook

对AddressBook.framework框架的封装

  1. iOS9.0最新通讯录获取框架

4.1 ContactsUI.framework == 方案1的替代品
特点: 面向对象, 使用简单. 有界面.
4.2 Contacts.framework == 方案2的替代品
特点: 面向对象, 使用简单. 无界面.


02 获取通讯录-AddressBookUI

  • 实现代码
   
      //1. 创建选择联系人的控制器
        let adressVC = ABPeoplePickerNavigationController()
        
        //2. 设置代理用来接受用户选择的联系人信息
        adressVC.peoplePickerDelegate = self
        
        //3. 弹出联系人控制器
        present(adressVC, animated: true, completion: nil)


//4. 实现代理
//5. 在对应的代理方法中获取联系人信息
    //取消选中联系人
    func peoplePickerNavigationControllerDidCancel(_ peoplePicker: ABPeoplePickerNavigationController)
    {
        print("取消选中联系人")
        
    }
    // 选择某一个联系人时调用
    func peoplePickerNavigationController(_ peoplePicker: ABPeoplePickerNavigationController, didSelectPerson person: ABRecord)
    {
        //ABRecord使用ABRecordCopyValue可以从一条Person记录中获取到对应的记录,
        //但是后续处理则需要根据记录的具体类型加以区分
        // 联系人里面的额记录, 分两个类型
       // 简单属性, 姓名 ABRecordRef 可以直接使用
       // 复杂属性, 联系人方式 家里电话, 办公电话 "标签" + "值"         ABMultiValueRef
        
        // Unmanaged<AnyObject>!
       // swift , 使用CoreFoundation框架里面的类型, 分为两种
       // 内存托管对象: 不需要我们程序员,手动去管理 CFString
       // 内存非托管对象: 需要我们程序员, 手动管理内存
       //              takeRetainedValue: 如果方法名称里面有create, copy,
       //              takeUnretainedValue: 如果方法名称里面有get
        //简单属性,
        let firstName = ABRecordCopyValue(person, kABPersonFirstNameProperty).takeRetainedValue() as! String
        let lastName = ABRecordCopyValue(person, kABPersonLastNameProperty).takeRetainedValue() as! String
        
        print(lastName, firstName)
        //复杂属性 取出联系人号码
        let multiValue = ABRecordCopyValue(person, kABPersonPhoneProperty).takeRetainedValue() as  ABMultiValue
        //取出号码个数
        let count = ABMultiValueGetCount(multiValue)
        for i in 0..<count
        {
            // 每一个电话号码(标签+值) Unmanaged<CFString>!
            //            Unmanaged
            let label = ABMultiValueCopyLabelAtIndex(multiValue, i).takeRetainedValue()

            let value = ABMultiValueCopyValueAtIndex(multiValue, i).takeRetainedValue() as! String
            print(label,value)
            
        }
 
    }
    // 选择某一个联系人某一个属性时调用
    // 如果上面一个选中某个联系人的方法, 实现了, 那么这个方法就不会再自行(因为界面压根都不会跳转到详情界面)
    // 除非, 你把上面的方法,注释
    func peoplePickerNavigationController(_ peoplePicker: ABPeoplePickerNavigationController, didSelectPerson person: ABRecord, property: ABPropertyID, identifier: ABMultiValueIdentifier)
    {
        print("选中某个联系人的某个属性")
        
    }

AddressBook

  • 实现代码
// 判断当前的授权状态, 如果没有授权, 则请求授权
        // 在开发当中, 一般把授权, 放到代理里面
        let status = ABAddressBookGetAuthorizationStatus()
        if status == .notDetermined //用户拒绝
        {// 请求访问通讯录的权限
            // 参数1: 通讯录对象
            // 参数2: 回调block
            let ab = ABAddressBookCreate().takeRetainedValue()
            ABAddressBookRequestAccessWithCompletion(ab)
            { (granted, error) in
                if granted
                {
                    print("授权成功")
                        
                }else
                {
                    print("授权失败")
                }
                
            }
            
        }

       //判断状态
        let status = ABAddressBookGetAuthorizationStatus()
        if status != .authorized
        {
            print("当前没有访问权限")
        }
        
        //获取所有的联系人
        //1. 创建通讯录对象
        let ad = ABAddressBookCreate().takeRetainedValue()
        
        //取出所有的联系人
        let array : CFArray = ABAddressBookCopyArrayOfAllPeople(ad).takeRetainedValue()
        // 2. 遍历里面所有的额对象记录
        let count = CFArrayGetCount(array)
        for i in 0..<count
        {
            // UnsafePointer<Void> == void * : 指向任意对象的zhizhen
            // 需要把它转换成为, 一个特定的对象, 才可以使用
            // swift 提供一个函数, 专门用于这种指针的转换
            // unsafeBitCast, 但是, 使用这个函数, 一定要注意, 这个函数, 非常不安全, 必须明确的知道, 我们真正的结果是什么, 否则, 转换会失败
            // 数组里面每一个对象, 都是一个联系人记录 ABRecord
            let recordPoint = CFArrayGetValueAtIndex(array, i)
            let record = unsafeBitCast(recordPoint, to: ABRecord.self)
            //简单属性
            let lastName = ABRecordCopyValue(record, kABPersonLastNameProperty).takeRetainedValue()
            let firstName = ABRecordCopyValue(record, kABPersonFirstNameProperty).takeRetainedValue()
            print(lastName,firstName)
            //复杂属性
            //电话号码
            let multierValue = ABRecordCopyValue(record, kABPersonPhoneProperty).takeRetainedValue()
            let count = ABMultiValueGetCount(multierValue)
            //遍历电话号码
            for j in 0..<count
            {
                let label = ABMultiValueCopyLabelAtIndex(multierValue, j).takeRetainedValue()
                let number = ABMultiValueCopyValueAtIndex(multierValue, j).takeRetainedValue()
                var phoneNnum = ""
                
                if number != nil
                {
                    phoneNnum = number as! String
                    
                }
                print(label, phoneNnum)
                
            }
        }
    
        
    }

IOS 9.0之后可以使用心得框架 ContactsUI.framework替代第一种方案

 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
    {
       //1.创建一个控制器
        let contackVC = CNContactPickerViewController()
        //1.1设置代理
        contackVC.delegate = self
        //2.弹出控制器
        present(contackVC, animated: true, completion: nil)
        
    }
        

}
extension ViewController : CNContactPickerDelegate
{
    //实现代理方法
    func contactPickerDidCancel(_ picker: CNContactPickerViewController)
    {
        print("取消选择联系人")
        
    }
    func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact)
    {
        //选择y一个联系人时候调用
        print("选择联系人")
        let familyName = contact.familyName
        let givenName = contact.givenName
        print(familyName,givenName)
        
        let phoneNumbers = contact.phoneNumbers
        for phoneNumber in phoneNumbers
        {
            let label = phoneNumber.label
            let value = phoneNumber.value
            
            print(label, value)
        }
        
    }
//    func contactPicker(_ picker: CNContactPickerViewController, didSelect contacts: [CNContact])
//    {//选择多个联系人时调用
//        print("选择多个联系人")
//
//    }
    
    // 选择某一个联系人的某一个属性时调用
        // 如果想要选择某一个属性, 需要把上面的方法注释
    //    func contactPicker(picker: CNContactPickerViewController, didSelectContactProperty contactProperty: CNContactProperty) {
    //         print("选择某一个联系人的某一个属性时调用")
    //    }
}

Contacts.framework使用,替代第二种方案

  • 代码实现
import UIKit
import Contacts

class ViewController: UIViewController
{

    //1. 创建联系人仓库
    @available(iOS 9.0, *)
       var store: CNContactStore  {
           return CNContactStore()
       }
    
    
    override func viewDidLoad()
    {
        super.viewDidLoad()
        
         // 判断授权状态, 请求授权
        if #available(iOS 9.0, *)
        {
            let status = CNContactStore.authorizationStatus(for: .contacts)
            if status == .notDetermined
            {
                // 请求授权
           // 1. 创建联系人仓库
           //            let store = CNContactStore()
           // 2. 请求授权
                let tempStore = store
                tempStore.requestAccess(for: .contacts)
                { (granted, error) in
                    if granted
                    {
                        print("授权成功")
                    }else
                    {
                        print("授权失败")
                    }
                    
                }
                
            }
        }
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
    {
        if #available(iOS 9.0, *)
        {
                    // 0. 判断是否授权成功
            let status = CNContactStore.authorizationStatus(for: .contacts)
            if status != .authorized
            {
                print("没有权限")
            }
            else
            {
                print("获得权限")
            }
            // 取出所有联系人
            // 1. 创建请求对象
            // 过滤一些字段(凡是写到这个数组里面的, 都代表, 你要获取的字段)
            let quest = CNContactFetchRequest(keysToFetch: [CNContactFamilyNameKey as NSString, CNContactPhoneNumbersKey as NSString])
            
            //开始便利
            do
            {
                let tempStore = store
                
                try tempStore.enumerateContacts(with: quest, usingBlock:
                { (contact, stop) in
                    let fanmilyName = contact.familyName
                    print(fanmilyName)
                    let phoneNumbers = contact.phoneNumbers
                
                    for num in phoneNumbers
                    {
                        let label = num.label
                        let numberStr = num.value
                        print(label , numberStr.stringValue)
                    }
                    //stop.pointee = true
  
                })
            } catch
            {
                print(error)
            }
            
        }
    }
}

相关文章

  • AddressBookFramework & Conta

    iOS之前是使用 AddressBookFramework 访问通讯录,但从 iOS 9.0 开始被 Contac...

  • IOS 通讯录 访问和使用

    01.通讯录简介 通讯录应用场景 最常见的是一些即时通讯APP, 关联联系人; 通讯录获取方案 AddressBo...

  • 重点 (二十九) : 通讯录

    如何访问用户的通讯录 在iOS中,有2个框架可以访问用户的通讯录 AddressBookUI.framework ...

  • iOS学习笔记29-系统服务(二)通讯录

    一、通讯录 iOS中的通讯录是存储在数据库中的,由于iOS的权限设计,开发人员是不允许直接访问通讯录数据库的,实现...

  • ios 访问通讯录

    - (void)requestAuthorizationForAddressBook { // 判断当前的...

  • iOS 访问通讯录

    iOS 9 之后,苹果增加新特性的库 - ContactsUI.framework 和 Contacts.fram...

  • ios9下vue使用踩坑记录

    问题描述 使用vue开发单页的通讯录选择器组件后。 在iOS 10 和 iOS 8下都正常运行。 就在iOS 9下...

  • iOS13&Xcode11适配问题

    1.通讯录权限问题iOS 13中将禁止应用开发者访问用户通讯录备注信息,需将keys中的CNContactNote...

  • 调用系统通讯录

    #import "ViewController.h" //iOS6开始, 要访问通讯录, 必须先授权. 不授权上架...

  • 通讯录技术

    通讯录技术 目标:获取通讯录中的信息.简称AB和CN. iOS9.0之前:(使用C语言的数据类型)1. Addre...

网友评论

      本文标题:IOS 通讯录 访问和使用

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