iOS中通讯录的开发

通讯录开发主要是获取用户手机中的联系人,进而可以在应用中添加好友

一 .如何访问通讯录

  (1)在iOS9之前,有两个框架可以访问用户的通讯录

    AddressBookUI.framework: 提供了联系人列表界面,联系人详情界面,添加练习人界面等,一般用于选择联系人

    AddressBook.framework: 纯C语言的API,仅仅是获的联系人数据,没有提供UI界面展示,需要自己搭建联系人展示界面,里面的数据类型大部分基于Core Foundation框架,使用起来极其蛋疼

  (2)在iOS9开始,也有两个框架可以访问用户的通讯录

            ContactsUI.framework: 对应AddressBookUI.framework

    Contacts.framework: 对应AddressBook.framework

 

二.代码演示

     (1)AddressBookUI的使用

        使用步骤

        1)创建选择联系人控制器

        2)设置代理

        3)实现代理方法(在代理方法中拿到用户选择的联系人)

        4)弹出控制器

       代码如下: 

import UIKit
import AddressBookUI

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        // 1.创建联系人选择的控制器
        let ppnc = ABPeoplePickerNavigationController()
        
        // 2.设置代理
        ppnc.peoplePickerDelegate = self
        
        // 3.弹出控制器
        present(ppnc, animated: true, completion: nil)
    }
}


extension ViewController : ABPeoplePickerNavigationControllerDelegate {
    // 用户选中了某一个联系人
    func peoplePickerNavigationController(_ peoplePicker: ABPeoplePickerNavigationController, didSelectPerson person: ABRecord) {
        // 1.获取联系人的姓名
        /*
         Unmanaged<CFTypeRef>? : 非托管对象
            * 在Swift和C语言进行混编的过程中,产生的一个临时对象,真正使用的时候需要将非托管对象,转成真正的对象才能进行使用
            * takeUnretainedValue : 表示在转化的过程中,不会对对象进行一次retain操作
            * takeRetainedValue : 表示在转化的过程中,有对对象进行一次retain操作
                注意:一旦使用takeRetainedValue,那么必须对之前的非托管对象进行一次release(),否则就会产生内存泄漏
                 let UnManageObjc = ABRecordCopyValue(person, kABPersonLastNameProperty)
                 let lastname = UnManageObjc?.takeRetainedValue() as? String
                 UnManageObjc?.release()
        */
        guard let lastname = ABRecordCopyValue(person, kABPersonLastNameProperty).takeUnretainedValue() as? String else { return }
        guard let firstname = ABRecordCopyValue(person, kABPersonFirstNameProperty).takeUnretainedValue() as? String else { return }
        print("姓名:\(firstname) \(lastname)")
        
        // 2.获取联系人的电话号码
        // ABMultiValue 类似于一个字典,里面有key/value
        // 2.1.从person中拷贝出来所有的电话号码
        let phones = ABRecordCopyValue(person, kABPersonPhoneProperty).takeUnretainedValue() as ABMultiValue
        // 2.2.遍历ABMultiValue中的所有电话
        // guard let count = phones.count else { return } 错误写法
        let count = ABMultiValueGetCount(phones)
        
        for i in 0..<count {
            let phoneLabel = ABMultiValueCopyLabelAtIndex(phones, i).takeUnretainedValue() as String
            guard let phoneValue = ABMultiValueCopyValueAtIndex(phones, i).takeUnretainedValue() as? String else { continue }
            print("phoneLabel:\(phoneLabel) phoneValue:\(phoneValue)")
        }
    }
}

          注意: 这里有一种对象 :Unmanaged<CFTypeRef>? : 非托管对象,这种对象是在Swift和C语言进行混编的过程中,出现的.需要用takeUnretainedValue() 或者 takeRetainedValue()进行转化.

          运行结果如下图:

      (2)AddressBook的使用

        1)获取用户的授权

          获取授权状态

          如果用户是未决定状态,则请求授权

        2)获取联系人信息

          获取授权状态

          如果是已经授权,则获取联系人信息

          创建通讯录对象

          获取通信录中所有的联系人

          遍历所有的联系人,获取联系人信息

      获取用户授权的代码实现,通常在应用启动时就询问用户授权

          AppDelegate中代码如下所示:

import UIKit
import AddressBook

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        
        // 1.获取用户的授权状态
        let status = ABAddressBookGetAuthorizationStatus()
        
        // 2.判断授权状态是否未决定
        if status == .notDetermined {
            // 2.1.创建通信录对象
            let addressBook = ABAddressBookCreate().takeUnretainedValue()
            
            // 2.2.请求授权
            ABAddressBookRequestAccessWithCompletion(addressBook, { (isFlag : Bool, error : CFError?) in
                if isFlag {
                    print("授权成功")
                } else {
                    print("授权失败")
                }
            })
        }
        
        return true
    }
}

      ViewController中代码如下所示:

import UIKit
import AddressBook

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        // 1.获取用户授权状态
        let status = ABAddressBookGetAuthorizationStatus()
        
        // 2.判断是否是已经授权
        guard status == .authorized else {
            return
        }
        
        // 3.创建通信录对象
        let addressBook = ABAddressBookCreate().takeUnretainedValue()
        
        // 4.从对象中,拷贝出来所有的联系人
        let peopleArray = ABAddressBookCopyArrayOfAllPeople(addressBook).takeUnretainedValue()
        
        // 5.遍历数组,获取每一个联系人
        let count = CFArrayGetCount(peopleArray)
        for i in 0..<count {
            // 5.1.获取指针
            let pointer = CFArrayGetValueAtIndex(peopleArray, i)
            
            // 5.2.获取指针指向的对象
            // unsafeBitCast : 将指针转成某一个对象
            let person = unsafeBitCast(pointer, to: ABRecord.self)
            
            // 5.3.获取该联系人的姓名
            guard let lastname = ABRecordCopyValue(person, kABPersonLastNameProperty).takeUnretainedValue() as? String else { continue }
            guard let firstname = ABRecordCopyValue(person, kABPersonFirstNameProperty).takeUnretainedValue() as? String else { continue }
            print("姓名:\(firstname) \(lastname)")
            
            // 5.4.获取电话号码
            let phones = ABRecordCopyValue(person, kABPersonPhoneProperty).takeUnretainedValue() as ABMultiValue
            let phoneCount = ABMultiValueGetCount(phones)
            for i in 0..<phoneCount {
                // let phoneLabel = ABMultiValueCopyLabelAtIndex(phones, i).takeUnretainedValue() as String
                guard let phoneValue = ABMultiValueCopyValueAtIndex(phones, i).takeUnretainedValue() as? String else { continue }
                print(phoneValue)
            }
        }
    }
}

      注意: 由于需要访问请求授权,需要在info.plist配置NSContactsUsageDescription这个key

      (3)ContactsUI的使用

        1)使用步骤

          创建选择联系人控制器

          设置代理

          实现代理方法(在代理中拿到用户选择的联系人)

          弹出控制器

        2)代码实现

import UIKit
import ContactsUI

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        // 1.创建联系人选择的控制器
        let cpvc = CNContactPickerViewController()
        
        // 2.设置代理
        cpvc.delegate = self
        
        // 3.弹出控制器
        present(cpvc, animated: true, completion: nil)
    }
}

extension ViewController : CNContactPickerDelegate {
    func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) {
        // 1.获取用户的姓名
        // lastname --> familyName
        // firstname --> givenname
        let lastname = contact.familyName
        let firstname = contact.givenName
        print("姓名:\(firstname) \(lastname)")
        
        // 2.获取用户电话号码(ABMultivalue)
        let phones = contact.phoneNumbers
        for phone in phones {
            let phoneLabel = phone.label
            let phoneValue = phone.value.stringValue
            print("phoneLabel:\(phoneLabel). phoneValue:\(phoneValue)")
        }
    }

}

输出结果和AddressBookUI.framework中的输出结果类似

      4)Contacts

                      1)获取用户的授权

          获取授权状态

          如果用户是未决定状态,则请求授权

        2)获取联系人信息

          获取授权状态

          如果是已经授权,则获取联系人信息

          创建通讯录对象

          获取通信录中所有的联系人

          遍历所有的联系人,获取联系人信息

      获取用户授权的代码实现,通常在应用启动时就询问用户授权,请求授权需要在info.plist配置NSContactsUsageDescription这个key

AppDelegate代码如下所示:

import UIKit
import Contacts

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        
        // 1.获取授权状态
        // CNContactStore --> 通信录对象
        let status = CNContactStore.authorizationStatus(for: .contacts)
        
        // 2.判断如果是未决定状态,请求授权
        if status == .notDetermined {
            // 2.1.创建通信录对象
            let store = CNContactStore()
            
            // 2.2.请求授权
            store.requestAccess(for: .contacts, completionHandler: { (isFlag : Bool, error : Error?) in
                if isFlag {
                    print("授权成功")
                } else {
                    print("授权失败")
                }
            })
        }
        
        return true
    }
}

ViewController中代码如下:

import UIKit
import Contacts

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        // 1.获取授权状态
        let status = CNContactStore.authorizationStatus(for: .contacts)
        
        // 2.判断是否是已经授权
        guard status == .authorized else {
            return
        }
        
        // 3.创建通信录对象
        let store = CNContactStore()
        
        // 4.从通信录中获取所有的联系人
        // 4.1.获取fetch,并且指定之后要获取联系人中的什么属性
        let keys = [CNContactFamilyNameKey as NSString, CNContactGivenNameKey as NSString, CNContactPhoneNumbersKey as NSString]
        
        // 4.2.创建请求对象
        let request = CNContactFetchRequest(keysToFetch: keys)
        
        // 4.3.遍历所有的联系人
        do {
            try store.enumerateContacts(with: request, usingBlock: { (contact : CNContact, stop : UnsafeMutablePointer<ObjCBool>) -> Void in
                // 1.获取姓名
                let lastname = contact.familyName
                let firstname = contact.givenName
                print(lastname, firstname)
                
                // 2.获取电话号码
                let phoneNumers = contact.phoneNumbers
                for phone in phoneNumers {
                    print(phone.label ?? "没有Label")
                    print(phone.value.stringValue)
                }
            })
        } catch {
            print(error)
        }
        
        
    }
}

转载于:https://www.cnblogs.com/muzichenyu/p/6084709.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值