2016-08-19 2 views
5

Ich möchte nur Kontakt geben Vorname und Nachname nach Telefonnummer. Ich habe das versucht, aber das ist zu langsam und CPU erreicht über% 120.iOS Kontakte Wie Sie Kontakt per Telefon holen

Auch wenn ich Phonenumber Kit für die Suche nach Kontakten verwenden seine zunehmende CPU und geben späte Antwort.

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

Irgendwelche Vorschläge oder Hilfe? –

+0

Glauben Sie nicht, dass es möglich ist – user3237732

+0

Ich versuche nur, Name und Nachname von der Telefonnummer zu bekommen und kann es nicht bekommen? Es ist interessant, wie kann whatsapp das tun? –

Antwort

13

Das Problem mit Ihrer Implementierung ist, dass Sie auf das Adressbuch in jeder Suche zugreifen, die Sie machen.

Wenn Sie stattdessen den Adressbuchinhalt nach dem ersten Zugriff im Speicher halten, erreichen Sie diese hohe CPU-Auslastung nicht.

  1. Zuerst einen faulen var in Ihrem Controller hält, die den Adreßbuch Inhalt halten:

    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 
    }() 
    
    1. Iterate durch den In-Memory-Array, wenn Sie schauen für einen Kontakt mit einer bestimmten Telefonnummer:

    .

    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 
    } 
    

ich es mit einem sehr großen Adressbuch getestet, es funktioniert reibungslos.

Hier ist der gesamte View-Controller als Referenz zusammengeflickt.

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

Ich verwendete flohei's answer für die Lazy Var Teil.

+1

ja Das ist schnell, aber es werden nicht alle Nummern in meiner Liste angezeigt. Zum Beispiel brauche ich einen Kontakt, aber ich habe eine Nummer mit Ländercode. Wenn der Kontakt nicht nach Ländercode gespeichert ist, kann ich ihn nicht abrufen. Was soll ich dafür tun? –

+1

Eigentlich ist das eine andere Frage als die, die Sie ursprünglich gestellt haben. Sie können die Zahlen der Benutzereingabe und die Zahlen aus dem Adressbuch einfach so formatieren, dass sie das gleiche Format haben. Dazu können Sie eine externe Bibliothek verwenden (wie https://github.com/marmelroy/PhoneNumberKit). –

+0

Eine andere Möglichkeit ist, den Ländercode zu entfernen - falls vorhanden. Dann vergleiche einfach die Flugnummer. –

Verwandte Themen