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)
        }
        
        
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM