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

iOS联系人如何通过电话号码获取联系人,ios,swift,ios9,contacts,Ios,Swift,Ios9,Contacts,我只想通过电话号码获得联系人的姓名和姓氏。我试过了,但是速度太慢了,cpu超过了%120 let contactStore = CNContactStore() let keys = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey] var contacts = [CNContact]() do {

我只想通过电话号码获得联系人的姓名和姓氏。我试过了,但是速度太慢了,cpu超过了%120

let contactStore = CNContactStore()
            let keys = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey]
            var contacts = [CNContact]()
            do {
                try contactStore.enumerateContactsWithFetchRequest(CNContactFetchRequest.init(keysToFetch: keys), usingBlock: { (contact, cursor) in
                    if (!contact.phoneNumbers.isEmpty) {
                        for phoneNumber in contact.phoneNumbers {
                            if let phoneNumberStruct = phoneNumber.value as? CNPhoneNumber {
                                do {
                                    let libPhone = try util.parseWithPhoneCarrierRegion(phoneNumberStruct.stringValue)
                                    let phoneToCompare = try util.getNationalSignificantNumber(libPhone)
                                    if formattedPhone == phoneToCompare {
                                        contacts.append(contact)
                                    }
                                }catch {
                                    print(error)
                                }
                            }

                        }
                    }
                })
                if contacts.count > 0 {
                    contactName = (contacts.first?.givenName)! + " " + (contacts.first?.familyName)!
                    print(contactName)
                    completionHandler(contactName)
                }
            }catch {
                print(error)
            }
另外,当我使用phonenumber工具包查找联系人时,它的cpu会不断增加,响应时间也会很晚

var result: [CNContact] = []
        let nationalNumber = PhoneNumberKit().parseMultiple([phoneNumber])
        let number = nationalNumber.first?.toNational()
        print(number)

        for contact in self.addressContacts {
            if (!contact.phoneNumbers.isEmpty) {

                let phoneNumberToCompareAgainst = number!.componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet).joinWithSeparator("")
                for phoneNumber in contact.phoneNumbers {
                    if let phoneNumberStruct = phoneNumber.value as? CNPhoneNumber {
                        let phoneNumberString = phoneNumberStruct.stringValue
                        let nationalContactNumber = PhoneNumberKit().parseMultiple([phoneNumberString])
                        let nationalContactNumberString = nationalContactNumber.first?.toNational()
                        if nationalContactNumberString == number {
                            result.append(contact)
                        }
                    }
                }
            }
        }

        return result

您的实现的问题在于,您在进行的每次搜索中都会访问地址簿

如果您在第一次访问后将地址簿内容保存在内存中,则不会达到如此高的CPU使用率

  • 首先在控制器中保存一个惰性变量,该变量将保存通讯簿内容:

    lazy var contacts: [CNContact] = {
        let contactStore = CNContactStore()
        let keysToFetch = [
            CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName),
            CNContactEmailAddressesKey,
            CNContactPhoneNumbersKey,
            CNContactImageDataAvailableKey,
            CNContactThumbnailImageDataKey]
    
        // Get all the containers
        var allContainers: [CNContainer] = []
        do {
            allContainers = try contactStore.containersMatchingPredicate(nil)
        } catch {
            print("Error fetching containers")
        }
    
        var results: [CNContact] = []
    
        // Iterate all containers and append their contacts to our results array
        for container in allContainers {
            let fetchPredicate = CNContact.predicateForContactsInContainerWithIdentifier(container.identifier)
    
            do {
                 let containerResults = try     contactStore.unifiedContactsMatchingPredicate(fetchPredicate, keysToFetch: keysToFetch)
                results.appendContentsOf(containerResults)
            } catch {
                print("Error fetching results for container")
            }
        }
    
        return results
    }()
    
  • 当您查找具有特定电话号码的联系人时,请遍历内存阵列:
  • 我用一个非常大的通讯录测试了它,它运行平稳。

    这里是整个视图控制器的补丁,以供参考

    import UIKit
    import Contacts
    
    class ViewController: UIViewController {
    
        lazy var contacts: [CNContact] = {
            let contactStore = CNContactStore()
            let keysToFetch = [
                    CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName),
                    CNContactEmailAddressesKey,
                    CNContactPhoneNumbersKey,
                    CNContactImageDataAvailableKey,
                    CNContactThumbnailImageDataKey]
    
            // Get all the containers
            var allContainers: [CNContainer] = []
            do {
                allContainers = try contactStore.containersMatchingPredicate(nil)
            } catch {
                print("Error fetching containers")
            }
    
            var results: [CNContact] = []
    
            // Iterate all containers and append their contacts to our results array
            for container in allContainers {
                let fetchPredicate = CNContact.predicateForContactsInContainerWithIdentifier(container.identifier)
    
                do {
                    let containerResults = try contactStore.unifiedContactsMatchingPredicate(fetchPredicate, keysToFetch: keysToFetch)
                    results.appendContentsOf(containerResults)
                } catch {
                    print("Error fetching results for container")
                }
            }
    
            return results
        }()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
    
            let contact = searchForContactUsingPhoneNumber("(555)564-8583")
            print(contact)
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    
        func searchForContactUsingPhoneNumber(phoneNumber: String) -> [CNContact] {
    
            var result: [CNContact] = []
    
            for contact in self.contacts {
                if (!contact.phoneNumbers.isEmpty) {
                    let phoneNumberToCompareAgainst = phoneNumber.componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet).joinWithSeparator("")
                    for phoneNumber in contact.phoneNumbers {
                        if let phoneNumberStruct = phoneNumber.value as? CNPhoneNumber {
                            let phoneNumberString = phoneNumberStruct.stringValue
                            let phoneNumberToCompare = phoneNumberString.componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet).joinWithSeparator("")
                            if phoneNumberToCompare == phoneNumberToCompareAgainst {
                                result.append(contact)
                            }
                        }
                    }
                }
            }
    
            return result
        }
    }
    

    我用于惰性变量部分。

    SWIFT 4更新

    1) 添加到.plist

    2) 如果您之前要求检查授权状态,请检查授权状态

    3) 打电话联系

    4) 这是获取联系人姓名或电话号码的功能

        func getNameFromContacts(number: String) -> String {
        var contactFetched : CNContact
        var contactName = ""
        if contacts.count > 0 {
    
            let numberToBeCompared = number.components(separatedBy:CharacterSet.decimalDigits.inverted).joined(separator: "")
            for c in contacts {
                for n in c.phoneNumbers {
                    if let numberRetrived = n.value as? CNPhoneNumber {
                         let numberRetrivedFixed = numberRetrived.stringValue.components(separatedBy:CharacterSet.decimalDigits.inverted).joined(separator: "")
                        if numberRetrivedFixed.elementsEqual(numberToBeCompared){
                            contactName = c.givenName
                            // OR get the contact --> c
                     contactFetched = c
    
                        }
                    }
                }
            }
    
            return contactName
    
        } else {
            return ""
        }
    }
    

    必须对Swift 5进行以下更改:

    
    lazy var contacts = {
                let contactStore = CNContactStore()
                let keysToFetch: [CNKeyDescriptor] = [
                    CNContactFormatter.descriptorForRequiredKeys(for: .fullName),
                    CNContactEmailAddressesKey as CNKeyDescriptor,
                    CNContactPhoneNumbersKey as CNKeyDescriptor,
                    CNContactImageDataAvailableKey as CNKeyDescriptor,
                    CNContactThumbnailImageDataKey as CNKeyDescriptor]
    
                // Get all the containers
                var allContainers: [CNContainer] = []
                do {
                    allContainers = try contactStore.containers(matching: nil)
                } catch {
                    print("Error fetching containers")
                }
    
                var results: [CNContact] = []
    
                // Iterate all containers and append their contacts to our results array
                for container in allContainers {
                    let fetchPredicate = CNContact.predicateForContactsInContainer(withIdentifier: container.identifier)
    
                    do {
                        let containerResults = try     contactStore.unifiedContacts(matching: fetchPredicate, keysToFetch: keysToFetch)
                        results.append(contentsOf: containerResults)
                    } catch {
                        print("Error fetching results for container")
                    }
                }
    
                return results
            }()
    
    对于迭代和发现:

        func searchForContactUsingPhoneNumber(phoneNumber: String) -> [CNContact] {
             var result: [CNContact] = []
    
             for contact in contacts {
                 if (!contact.phoneNumbers.isEmpty) {
                    let phoneNumberToCompareAgainst = phoneNumber.components(separatedBy: NSCharacterSet.decimalDigits.inverted).joined(separator: "")
                     for phoneNumber in contact.phoneNumbers {
                         if let phoneNumberStruct = phoneNumber.value as? CNPhoneNumber {
                             let phoneNumberString = phoneNumberStruct.stringValue
                            let phoneNumberToCompare = phoneNumberString.components(separatedBy: NSCharacterSet.decimalDigits.inverted).joined(separator: "")
                             if phoneNumberToCompare == phoneNumberToCompareAgainst {
                                 result.append(contact)
                             }
                         }
                     }
                  }
             }
    
             return result
        }
    
    

    有什么建议或帮助吗?不认为有可能我只是想从电话号码中查到姓名,但查不到?这很有趣,whatsapp如何做到这一点?是的,这很快,但它并没有获取我列表中的所有号码。例如,我需要获取联系人,但我有带国家代码的号码。因此,如果联系人未按国家代码保存,我将无法获取它。我该怎么办?事实上,这和你最初问的问题不同。您只需将用户输入的数字和通讯簿中的数字格式化为相同的格式,您可以使用外部库(如)。另一个选项是删除国家代码(如果存在)。那就比较一下飞机号码吧。不酷,你不应该在得到答案后再修改问题@MuratKaya我一直在关注你的这个话题,你从MatanLachmish那里得到了一个很好的直接答案。现在您已经编辑并更改了原始问题。这是错误的,完美。谢谢
        if CNContactStore.authorizationStatus(for: .contacts) == .authorized {
            getContacts()
    
        }
    
        var contacts = [CNContact]()
    
        func getContacts(){
    
        let contactStore = CNContactStore()
        let keys = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey, CNContactImageDataAvailableKey, CNContactThumbnailImageDataKey]
        let request = CNContactFetchRequest(keysToFetch: keys as [CNKeyDescriptor])
        request.sortOrder = CNContactSortOrder.givenName
    
        do {
            try contactStore.enumerateContacts(with: request) {
                (contact, stop) in
                self.contacts.append(contact)
            }
        }
        catch {
            print("unable to fetch contacts")
        }
    }
    
        func getNameFromContacts(number: String) -> String {
        var contactFetched : CNContact
        var contactName = ""
        if contacts.count > 0 {
    
            let numberToBeCompared = number.components(separatedBy:CharacterSet.decimalDigits.inverted).joined(separator: "")
            for c in contacts {
                for n in c.phoneNumbers {
                    if let numberRetrived = n.value as? CNPhoneNumber {
                         let numberRetrivedFixed = numberRetrived.stringValue.components(separatedBy:CharacterSet.decimalDigits.inverted).joined(separator: "")
                        if numberRetrivedFixed.elementsEqual(numberToBeCompared){
                            contactName = c.givenName
                            // OR get the contact --> c
                     contactFetched = c
    
                        }
                    }
                }
            }
    
            return contactName
    
        } else {
            return ""
        }
    }
    
    
    lazy var contacts = {
                let contactStore = CNContactStore()
                let keysToFetch: [CNKeyDescriptor] = [
                    CNContactFormatter.descriptorForRequiredKeys(for: .fullName),
                    CNContactEmailAddressesKey as CNKeyDescriptor,
                    CNContactPhoneNumbersKey as CNKeyDescriptor,
                    CNContactImageDataAvailableKey as CNKeyDescriptor,
                    CNContactThumbnailImageDataKey as CNKeyDescriptor]
    
                // Get all the containers
                var allContainers: [CNContainer] = []
                do {
                    allContainers = try contactStore.containers(matching: nil)
                } catch {
                    print("Error fetching containers")
                }
    
                var results: [CNContact] = []
    
                // Iterate all containers and append their contacts to our results array
                for container in allContainers {
                    let fetchPredicate = CNContact.predicateForContactsInContainer(withIdentifier: container.identifier)
    
                    do {
                        let containerResults = try     contactStore.unifiedContacts(matching: fetchPredicate, keysToFetch: keysToFetch)
                        results.append(contentsOf: containerResults)
                    } catch {
                        print("Error fetching results for container")
                    }
                }
    
                return results
            }()
    
        func searchForContactUsingPhoneNumber(phoneNumber: String) -> [CNContact] {
             var result: [CNContact] = []
    
             for contact in contacts {
                 if (!contact.phoneNumbers.isEmpty) {
                    let phoneNumberToCompareAgainst = phoneNumber.components(separatedBy: NSCharacterSet.decimalDigits.inverted).joined(separator: "")
                     for phoneNumber in contact.phoneNumbers {
                         if let phoneNumberStruct = phoneNumber.value as? CNPhoneNumber {
                             let phoneNumberString = phoneNumberStruct.stringValue
                            let phoneNumberToCompare = phoneNumberString.components(separatedBy: NSCharacterSet.decimalDigits.inverted).joined(separator: "")
                             if phoneNumberToCompare == phoneNumberToCompareAgainst {
                                 result.append(contact)
                             }
                         }
                     }
                  }
             }
    
             return result
        }