iOS Contacts Framework:如何通过电话号码获取联系人

时间:2022-01-01 22:55:35

I have a custom User class which stores the phone number of the user.

我有一个自定义用户类,用于存储用户的电话号码。

class User {
  let phoneNumber: String
}

How do I get the corresponding contact from the users contact book?

如何从用户联系簿获取相应的联系人?

I tried the following but it seems like this works just for the contacts name because I'm always getting nil:

我尝试了以下但似乎这只适用于联系人名称,因为我总是得到零:

let predicate = CNContact.predicateForContactsMatchingName(userInstance.phoneNumber)
let keysToFetch = [CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName), CNContactPhoneNumbersKey]

// Is already permitted
try! CNContactStore().unifiedContactsMatchingPredicate(predicate, keysToFetch: keysToFetch).first  // This returns nil

I've searched in the docs but I didn't find a proper solution.

我在文档中搜索过但我找不到合适的解决方案。

3 个解决方案

#1


4  

let contactStroe = CNContactStore()
        let keysToFetch = [
            CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName),
            CNContactEmailAddressesKey,
            CNContactPhoneNumbersKey,
            CNContactImageDataAvailableKey,
            CNContactThumbnailImageDataKey]
contactStroe.requestAccessForEntityType(.Contacts, completionHandler: { (granted, error) -> Void in
if granted {
                let predicate = CNContact.predicateForContactsInContainerWithIdentifier(contactStroe.defaultContainerIdentifier())
                var contacts: [CNContact]! = []
                do {
                    contacts = try contactStroe.unifiedContactsMatchingPredicate(predicate, keysToFetch: keysToFetch)// [CNContact]
                }catch {

                }
for contact in contacts {
                    var phoneStr = ""
                    var nameStr = ""
                    var number: CNPhoneNumber!
                    if contact.phoneNumbers.count > 0 {
                        number = contact.phoneNumbers[0].value as! CNPhoneNumber
                        phoneStr = number.stringValue.stringByReplacingOccurrencesOfString("-", withString: "")
                    }
                    nameStr = contact.familyName + contact.givenName
                    if !nameStr.isEmpty && !phoneStr.isEmpty {
                        let friend = YFriendsModel()
                        friend.name = nameStr
                        friend.phone = phoneStr
                        self.friendArr.append(friend)
                    }

                }

        })

this is my way, you can have a test

这是我的方式,你可以进行测试

#2


2  

You can't.

This is a stupid solution as a huge workaround.

作为一个巨大的解决方案,这是一个愚蠢的解决方案。

  1. Read each contact
  2. 阅读每个联系人

  3. Normalize the phone number (not the easiest thing to do!)
  4. 规范化电话号码(不是最简单的事情!)

  5. Cache contacts into a [String : Contact]
  6. 将联系人缓存到[String:Contact]

Then you can lookup contacts with contacts[phone_number]?

然后你可以查找联系人[phone_number]的联系人?

#3


0  

Swift 3 A nice solution, taking care also of efficiency:

Swift 3一个很好的解决方案,也注重效率:

    func getAllContacts() {
        let status = CNContactStore.authorizationStatus(for: CNEntityType.contacts) as CNAuthorizationStatus

        if status == CNAuthorizationStatus.denied {
            self.showAccessContactsDeniedAlert()
            return
        }
        let contactStore = CNContactStore()
        let keysToFetch = [
            CNContactFormatter.descriptorForRequiredKeys(for: .fullName),
            CNContactEmailAddressesKey,
            CNContactPhoneNumbersKey,
            CNContactImageDataAvailableKey,
            CNContactThumbnailImageDataKey] as [Any]
        let request = CNContactFetchRequest(keysToFetch:keysToFetch as! [CNKeyDescriptor])
        do {
        try contactStore.enumerateContacts(with: request, usingBlock: { (contact:CNContact, stop:UnsafeMutablePointer<ObjCBool>) -> Void in
            print(contact)
            for email in contact.emailAddresses {
                var dict = [String:String]()
                dict["name"] = contact.familyName + contact.givenName
                dict["email"] = email.value
                self.allContacts.add(dict)
            }
        })
        } catch {
            //catch
        }
    }

In this case I save name and email into a dict and I add it to a class variable called allContacts.

在这种情况下,我将名称和电子邮件保存到dict中,然后将其添加到名为allContacts的类变量中。

Note that a contact can have more than one email, so I create a dict for any email address in this case

请注意,联系人可以有多个电子邮件,因此我在这种情况下为任何电子邮件地址创建一个dict

#1


4  

let contactStroe = CNContactStore()
        let keysToFetch = [
            CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName),
            CNContactEmailAddressesKey,
            CNContactPhoneNumbersKey,
            CNContactImageDataAvailableKey,
            CNContactThumbnailImageDataKey]
contactStroe.requestAccessForEntityType(.Contacts, completionHandler: { (granted, error) -> Void in
if granted {
                let predicate = CNContact.predicateForContactsInContainerWithIdentifier(contactStroe.defaultContainerIdentifier())
                var contacts: [CNContact]! = []
                do {
                    contacts = try contactStroe.unifiedContactsMatchingPredicate(predicate, keysToFetch: keysToFetch)// [CNContact]
                }catch {

                }
for contact in contacts {
                    var phoneStr = ""
                    var nameStr = ""
                    var number: CNPhoneNumber!
                    if contact.phoneNumbers.count > 0 {
                        number = contact.phoneNumbers[0].value as! CNPhoneNumber
                        phoneStr = number.stringValue.stringByReplacingOccurrencesOfString("-", withString: "")
                    }
                    nameStr = contact.familyName + contact.givenName
                    if !nameStr.isEmpty && !phoneStr.isEmpty {
                        let friend = YFriendsModel()
                        friend.name = nameStr
                        friend.phone = phoneStr
                        self.friendArr.append(friend)
                    }

                }

        })

this is my way, you can have a test

这是我的方式,你可以进行测试

#2


2  

You can't.

This is a stupid solution as a huge workaround.

作为一个巨大的解决方案,这是一个愚蠢的解决方案。

  1. Read each contact
  2. 阅读每个联系人

  3. Normalize the phone number (not the easiest thing to do!)
  4. 规范化电话号码(不是最简单的事情!)

  5. Cache contacts into a [String : Contact]
  6. 将联系人缓存到[String:Contact]

Then you can lookup contacts with contacts[phone_number]?

然后你可以查找联系人[phone_number]的联系人?

#3


0  

Swift 3 A nice solution, taking care also of efficiency:

Swift 3一个很好的解决方案,也注重效率:

    func getAllContacts() {
        let status = CNContactStore.authorizationStatus(for: CNEntityType.contacts) as CNAuthorizationStatus

        if status == CNAuthorizationStatus.denied {
            self.showAccessContactsDeniedAlert()
            return
        }
        let contactStore = CNContactStore()
        let keysToFetch = [
            CNContactFormatter.descriptorForRequiredKeys(for: .fullName),
            CNContactEmailAddressesKey,
            CNContactPhoneNumbersKey,
            CNContactImageDataAvailableKey,
            CNContactThumbnailImageDataKey] as [Any]
        let request = CNContactFetchRequest(keysToFetch:keysToFetch as! [CNKeyDescriptor])
        do {
        try contactStore.enumerateContacts(with: request, usingBlock: { (contact:CNContact, stop:UnsafeMutablePointer<ObjCBool>) -> Void in
            print(contact)
            for email in contact.emailAddresses {
                var dict = [String:String]()
                dict["name"] = contact.familyName + contact.givenName
                dict["email"] = email.value
                self.allContacts.add(dict)
            }
        })
        } catch {
            //catch
        }
    }

In this case I save name and email into a dict and I add it to a class variable called allContacts.

在这种情况下,我将名称和电子邮件保存到dict中,然后将其添加到名为allContacts的类变量中。

Note that a contact can have more than one email, so I create a dict for any email address in this case

请注意,联系人可以有多个电子邮件,因此我在这种情况下为任何电子邮件地址创建一个dict