2016-08-19 111 views
5

我只想通过电话号码联系给定的姓名和姓氏。我试过这个,但是这太慢了,cpu超过了120%。iOS联系方式如何通过电话获取联系人号码

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 
+0

任何建议或帮助? –

+0

不要认为这是可能的 – user3237732

+0

我只是想从电话号码得到姓名,并不能得到它?这很有趣,那么whatsapp怎么做呢? –

回答

13

您实施的问题是您在每次搜索中都要访问地址簿。

如果相反,您将在第一次访问后保留内存中的地址簿内容,您将无法达到此高CPU使用率。

  1. 首先拿在控制器懒VAR将保存地址簿的内容:

    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 
    }() 
    
    通过内存阵列
  2. 迭代当你正在寻找对于与特定电话号码的联系人:

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 
} 

我有一个非常大的地址簿进行了测试,它工作的顺利进行。

这里是整个视图控制器修补在一起作为参考。

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

我使用了flohei's answer作为lazy var part。

+1

是的这很快,但它并没有得到我列表中的所有数字。例如,我需要获取联系人,但我有国家代码的号码。所以如果联系人没有通过国家代码保存,我无法获取它。我应该怎么做 –

+1

其实这是一个与你最初提出的问题不同的问题。您可以简单地将用户输入的数字和地址簿中的数字格式化为相同的格式,您可以使用外部库(例如https://github.com/marmelroy/PhoneNumberKit)。 –

+0

另一个选择是删除国家代码 - 如果它存在。然后,只需比较飞机编号。 –

相关问题