2016-08-19 16 views
5

Chcę tylko uzyskać kontakt podając nazwisko i imię i nazwisko przez numer telefonu. Próbowałem tego, ale jest to zbyt wolne i procesor uderza ponad% 120.iOS Kontakt Jak pobrać kontakt przez telefon Numer

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

Również gdy używam zestawu telefonicznego do wyszukiwania kontaktów, jego rosnący procesor i dawanie opóźnionej odpowiedzi.

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

Wszelkie sugestie lub pomoc? –

+0

Nie sądzę, że to możliwe – user3237732

+0

Próbuję tylko uzyskać imię i nazwisko z numeru telefonu i nie mogę go uzyskać? To ciekawe, jak może to zrobić WhatsApp? –

Odpowiedz

13

Problem z implementacją polega na tym, że dostęp do książki adresowej odbywa się przy każdym wyszukiwaniu.

Jeśli zamiast tego będziesz przechowywać w pamięci zawartość książki adresowej po pierwszym dostępie, nie osiągniesz tak wysokiego obciążenia procesora.

  1. Najpierw przytrzymaj leniwe var w kontrolerze, który będzie trzymać zawartość Książka adresowa:

    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. iterację tablicy w pamięci, gdy szukasz dla kontaktu z określonym numerem telefonu:

    .

    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 
    } 
    

ja testowałem to z bardzo dużym książki adresowej, działa płynnie.

Oto cały kontroler widoku połączony ze sobą w celach informacyjnych.

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

Użyłem flohei's answer dla lazy części var.

+1

tak Szybko, ale nie dostaje wszystkich liczb z mojej listy. Na przykład potrzebuję pobrać kontakt, ale mam numer z kodem kraju. Jeśli kontakt nie zostanie zapisany według kodu kraju, nie mogę go pobrać. Co powinienem zrobić, aby to zrobić? –

+1

W rzeczywistości jest to inne pytanie niż pierwotnie zadawane. Możesz po prostu sformatować numery wprowadzone przez użytkownika i numery z książki adresowej, aby mieć ten sam format, możesz użyć do tego zewnętrznej biblioteki (np. Https://github.com/marmelroy/PhoneNumberKit). –

+0

Inną opcją jest usunięcie kodu kraju - jeśli istnieje. Następnie porównaj numer samolotu. –

Powiązane problemy