Swift:JKContactsKit 獲取通訊錄的聯(lián)系人

JKSwiftExtension,測試用例在 JKContactsKitViewController 里面
目錄:

  • 1、簡介和CNKeyDescriptor的key介紹
  • 2襟铭、通訊錄的基本使用
    • 獲取授權狀態(tài)
    • 查詢出所有通訊錄信息
    • 添加新聯(lián)系人
    • 更新聯(lián)系人
    • 刪除聯(lián)系人

一、簡介和CNKeyDescriptor的key介紹

  • 1.1粥惧、在 iOS9.0 之前, 我們只能通過 AddressBook 框架來獲取通訊錄聯(lián)系人信息抛腕。但 AddressBook framework 語法很奇怪,同時也十分難用啰劲。所以蘋果從 iOS9.0 開始推出的全新的聯(lián)系人框架 Contacts FrameWork 作為替代,同時將原來的 AddressBook 給廢棄掉板丽。

  • 1.2呈枉、Contacts FrameWork 同樣包含兩種訪問通訊錄的方式:

    • ContactsUI.framework 框架 : 通過系統(tǒng)提供的通訊錄交互界面來訪問(替代原先的 AddressBookUI.framework)
    • Contacts.framework 框架 : 沒有界面,通過代碼來獲取所有聯(lián)系人信息(替代原先的 AddressBook.framework)

    由于蘋果安全策略更新埃碱,在使用 Xcode8 開發(fā)時猖辫,需要在 Info.plist 配置請求通訊錄的相關描述字段(Privacy - Contacts Usage Description

  • 1.3、CNKeyDescriptor的key介紹

    //  標識符
    @available(iOS 9.0, *)
    public let CNContactIdentifierKey: String
    // 姓名前綴
    @available(iOS 9.0, *)
    public let CNContactNamePrefixKey: String
    // 姓名
    @available(iOS 9.0, *)
    public let CNContactGivenNameKey: String
    // 中間名
    @available(iOS 9.0, *)
    public let CNContactMiddleNameKey: String
    // 姓氏
    @available(iOS 9.0, *)
    public let CNContactFamilyNameKey: String
    // 之前的姓氏(ex:國外的女士)
    @available(iOS 9.0, *)
    public let CNContactPreviousFamilyNameKey: String
    // 姓名后綴
    @available(iOS 9.0, *)
    public let CNContactNameSuffixKey: String
    // 昵稱
    @available(iOS 9.0, *)
    public let CNContactNicknameKey: String
    // 公司(組織)
    @available(iOS 9.0, *)
    public let CNContactOrganizationNameKey: String
    // 部門
    @available(iOS 9.0, *)
    public let CNContactDepartmentNameKey: String
    // 職位
    @available(iOS 9.0, *)
    public let CNContactJobTitleKey: String
    // 名字的拼音或音標
    @available(iOS 9.0, *)
    public let CNContactPhoneticGivenNameKey: String
    // 中間名的拼音或音標
    @available(iOS 9.0, *)
    public let CNContactPhoneticMiddleNameKey: String
    // 形式的拼音或音標
    @available(iOS 9.0, *)
    public let CNContactPhoneticFamilyNameKey: String
    // 公司(組織)的拼音或音標(iOS10 才開始存在的呢)
    @available(iOS 10.0, *)
    public let CNContactPhoneticOrganizationNameKey: String
    // 生日
    @available(iOS 9.0, *)
    public let CNContactBirthdayKey: String
    // 農(nóng)歷
    @available(iOS 9.0, *)
    public let CNContactNonGregorianBirthdayKey: String
    // 備注
    @available(iOS 9.0, *)
    public let CNContactNoteKey: String
    // 頭像
    @available(iOS 9.0, *)
    public let CNContactImageDataKey: String
    // 頭像的縮略圖
    @available(iOS 9.0, *)
    public let CNContactThumbnailImageDataKey: String
    // 頭像是否可用
    @available(iOS 9.0, *)
    public let CNContactImageDataAvailableKey: String
    // 類型
    @available(iOS 9.0, *)
    public let CNContactTypeKey: String
    // 電話號碼
    @available(iOS 9.0, *)
    public let CNContactPhoneNumbersKey: String
    // 郵箱地址
    @available(iOS 9.0, *)
    public let CNContactEmailAddressesKey: String
    // 住址
    @available(iOS 9.0, *)
    public let CNContactPostalAddressesKey: String
    // 其他日期
    @available(iOS 9.0, *)
    public let CNContactDatesKey: String
    // url地址
    @available(iOS 9.0, *)
    public let CNContactUrlAddressesKey: String
    // 關聯(lián)人
    @available(iOS 9.0, *)
    public let CNContactRelationsKey: String
    // 社交
    @available(iOS 9.0, *)
    public let CNContactSocialProfilesKey: String
    // 即時通信
    @available(iOS 9.0, *)
    public let CNContactInstantMessageAddressesKey: String
    

二砚殿、通訊錄的基本使用

  • 2.1啃憎、獲取授權狀態(tài)

    // MARK: 1.1、獲取授權狀態(tài)
    /// 獲取授權狀態(tài)
    /// - Returns: 授權狀態(tài)
    static func authorizationStatus() -> CNAuthorizationStatus {
        // 獲取授權狀態(tài)
        return CNContactStore.authorizationStatus(for: .contacts)
    }
    
  • 2.2似炎、查詢出所有通訊錄信息

    // MARK: 1.2辛萍、獲取通訊錄的信息
    /// 獲取通訊錄的信息
    /// - Parameter keys: 獲取Fetch,并且指定之后要獲取聯(lián)系人中的什么屬性
    ///   - completion: 結果閉包
    static func selectContactsData(keys: [String] = [CNContactFamilyNameKey, CNContactGivenNameKey, CNContactOrganizationNameKey, CNContactPhoneNumbersKey, CNContactNicknameKey], completion: @escaping (([CNContact], Error?) -> Void)) {
         // 創(chuàng)建通訊錄對象
         let store = CNContactStore()
         store.requestAccess(for: .contacts) {(granted, error) in
             if (granted) && (error == nil) {
                 // 創(chuàng)建請求對象 需要傳入一個(keysToFetch: [CNKeyDescriptor]) 包含'CNKeyDescriptor'類型的數(shù)組
                 let request = CNContactFetchRequest(keysToFetch: keys as [CNKeyDescriptor])
                 do {
                     var contacts: [CNContact] = []
                     // 需要傳入一個CNContactFetchRequest
                     try store.enumerateContacts(with: request, usingBlock: {(contact : CNContact, stop : UnsafeMutablePointer) -> Void in
                         contacts.append(contact)
                     })
                     completion(contacts, nil)
                 } catch {
                     completion([], nil)
                 }
             } else {
                 completion([], error)
             }
         }
    }
    
  • 2.3、添加新聯(lián)系人

    // MARK: 1.3羡藐、添加新聯(lián)系人
    /// 添加新聯(lián)系人
    /// - Parameters:
    ///   - contact: 聯(lián)系人的信息
    ///   - completion: 結果閉包
    static func addContactItem(contact: CNMutableContact, completion: @escaping ((Bool, Error?) -> Void)) {
         // 創(chuàng)建通訊錄對象
         let store = CNContactStore()
         store.requestAccess(for: .contacts) {(granted, error) in
             if (granted) && (error == nil) {
                 // 添加聯(lián)系人請求
                 let saveRequest = CNSaveRequest()
                 saveRequest.add(contact, toContainerWithIdentifier: nil)
                 do {
                     // 寫入聯(lián)系人
                     try store.execute(saveRequest)
                     completion(true, nil)
                 } catch {
                     completion(true, error)
                }
             } else {
                 completion(false, error)
             }
         }
    }
    
  • 2.4贩毕、更新聯(lián)系人

    // MARK: 1.4、更新聯(lián)系人
    /// 更新聯(lián)系人
    /// - Parameters:
    ///   - identifier: 唯一標識符
    ///   - familyName: 姓氏
    ///   - givenName: 名字
    ///   - phoneNumbers: 手機號碼數(shù)組
    ///   - keys: key
    ///   - completion: 結果閉包
    static func updateContactItem(identifier: String, familyName: String, givenName: String, phoneNumbers: [CNLabeledValue<CNPhoneNumber>], keys: [String] = [CNContactFamilyNameKey, CNContactGivenNameKey, CNContactOrganizationNameKey, CNContactPhoneNumbersKey, CNContactNicknameKey], completion: @escaping ((Bool, Error?) -> Void)) {
      // 創(chuàng)建通訊錄對象
      let store = CNContactStore()
      store.requestAccess(for: .contacts) {(granted, error) in
          if (granted) && (error == nil) {
              guard let itemContact = try? store.unifiedContact(withIdentifier: identifier, keysToFetch: keys as [CNKeyDescriptor]) else {
                  return
              }
              let mutableContact = itemContact.mutableCopy() as! CNMutableContact
              mutableContact.familyName = familyName
              mutableContact.givenName = givenName
              mutableContact.phoneNumbers = phoneNumbers
              // 修改聯(lián)系人請求
              let request = CNSaveRequest()
              request.update(mutableContact)
              do {
                  // 修改聯(lián)系人
                  try store.execute(request)
                  completion(true, error)
              } catch {
                  completion(false, error)
              }
          } else {
              completion(false, error)
          }
      }
    }
    
  • 2.5仆嗦、刪除聯(lián)系人

    // MARK: 1.5辉阶、刪除聯(lián)系人
    /// 刪除聯(lián)系人
    /// - Parameters:
    ///   - identifier: 唯一標識符
    ///   - keys: key
    ///   - completion: 結果閉包
    static func deleteContactItem(identifier: String, keys: [String] = [CNContactFamilyNameKey, CNContactGivenNameKey, CNContactOrganizationNameKey, CNContactPhoneNumbersKey, CNContactNicknameKey], completion: @escaping ((Bool, Error?) -> Void)) {
        // 創(chuàng)建通訊錄對象
        let store = CNContactStore()
        store.requestAccess(for: .contacts) {(granted, error) in
            if (granted) && (error == nil) {
                guard let itemContact = try? store.unifiedContact(withIdentifier: identifier, keysToFetch: keys as [CNKeyDescriptor]) else {
                    return
                }
                let mutableContact = itemContact.mutableCopy() as! CNMutableContact
                // 刪除聯(lián)系人請求
                let request = CNSaveRequest()
                request.delete(mutableContact)
                do {
                    // 執(zhí)行操作
                    try store.execute(request)
                    completion(true, error)
                } catch {
                    completion(false, error)
                }
            } else {
                completion(false, error)
            }
        }
    }
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市瘩扼,隨后出現(xiàn)的幾起案子谆甜,更是在濱河造成了極大的恐慌,老刑警劉巖集绰,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件规辱,死亡現(xiàn)場離奇詭異,居然都是意外死亡栽燕,警方通過查閱死者的電腦和手機罕袋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門改淑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人炫贤,你說我怎么就攤上這事溅固。” “怎么了兰珍?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵侍郭,是天一觀的道長。 經(jīng)常有香客問我掠河,道長亮元,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任唠摹,我火速辦了婚禮爆捞,結果婚禮上,老公的妹妹穿的比我還像新娘勾拉。我一直安慰自己煮甥,他們只是感情好,可當我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布藕赞。 她就那樣靜靜地躺著成肘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪斧蜕。 梳的紋絲不亂的頭發(fā)上双霍,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天,我揣著相機與錄音批销,去河邊找鬼洒闸。 笑死,一個胖子當著我的面吹牛均芽,可吹牛的內(nèi)容都是我干的丘逸。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼掀宋,長吁一口氣:“原來是場噩夢啊……” “哼鸣个!你這毒婦竟也來了?” 一聲冷哼從身側響起布朦,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎昼窗,沒想到半個月后是趴,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡澄惊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年唆途,在試婚紗的時候發(fā)現(xiàn)自己被綠了富雅。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡肛搬,死狀恐怖没佑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情温赔,我是刑警寧澤蛤奢,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站陶贼,受9級特大地震影響啤贩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜拜秧,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一痹屹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧枉氮,春花似錦志衍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至佃牛,卻和暖如春淹辞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背俘侠。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工象缀, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人爷速。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓央星,卻偏偏與公主長得像,于是被迫代替她去往敵國和親惫东。 傳聞我的和親對象是個殘疾皇子莉给,可洞房花燭夜當晚...
    茶點故事閱讀 42,834評論 2 345