iOS Contacts Framework: как получить контакты по номеру телефона

У меня есть собственный класс User, в котором хранится номер телефона пользователя.

class User {
  let phoneNumber: String
}

Как мне получить соответствующий контакт из книги контактов пользователей?

Я пробовал следующее, но похоже, что это работает только для имени контакта, потому что я всегда получаю 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

Я искал в документах, но не нашел подходящего решения.


person Tobias    schedule 17.01.2016    source источник


Ответы (3)


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

                }

        })

это мой путь, вы можете пройти тест

person xiaoming    schedule 17.01.2016
comment
Это выглядит как хороший способ, но мне интересно, есть ли более эффективный способ, чем получение всех контактов и повторение их. Что делать, если у пользователя 1000 или даже больше контактов? Вероятно, это будет довольно медленно. - person Tobias; 17.01.2016
comment
Я действительно игнорирую его эффективность прямо сейчас, вы можете написать это в другой поток - person xiaoming; 17.01.2016
comment
Спасибо, как раз то, что мне было нужно - person Oblivionkey3; 19.02.2018

Вы не можете.

Это глупое решение в качестве огромного обходного пути.

  1. Читать каждый контакт
  2. Нормализовать номер телефона (не самое простое дело!)
  3. Кэшировать контакты в [String : Contact]

Затем вы можете искать контакты с помощью contacts[phone_number]?

person William Entriken    schedule 23.09.2016

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

В этом случае я сохраняю имя и адрес электронной почты в словаре и добавляю их в переменную класса с именем allContacts.

Обратите внимание, что у контакта может быть более одного адреса электронной почты, поэтому в этом случае я создаю словарь для любого адреса электронной почты.

person Andrea.Ferrando    schedule 30.05.2017