web-dev-qa-db-fra.com

Swift Utilisation de Contacts Framework, effectuez une recherche à l'aide d'un numéro de téléphone pour obtenir le nom et l'image de l'utilisateur

J'ai une API qui renvoie les numéros de téléphone au format: + 1415xxxxxxx (E164)

À l'heure actuelle, ces numéros sont placés dans la cellule d'un UITableView et sont présentés comme prévu. Toutefois, j'aimerais pouvoir rechercher les contacts des utilisateurs sur le téléphone pour voir s'il existe une correspondance - si également renvoyer le prénom , nom et photo connue.

En consultant les pages Apple ( https://developer.Apple.com/library/watchos/documentation/Contacts/Reference/Contacts_Framework/index.html

 import ContactsUI

mais alors je ne suis pas sûr, est-ce que je charge le contactDB dans un dictionnaire puis le recherche? Je peux trouver beaucoup de choses sur la recherche par nom et moins sur la recherche par numéro: 

  let predicate = CNContact.predicateForContactsMatchingName("Sam") 

J'essaie d'obtenir une fonction que je peux appeler, qui effectue une recherche à l'aide du numéro de téléphone et me renvoie le prénom, le nom et l'image. 

  func searchForContactUsingNumber(PhoneNumber: String)
 {

 // Search Via phoneNumber
  let store = CNContactStore()
  let contacts = try store.unifiedContactsMatchingPredicate(CNContact.predicateForContactsMatchingPhoneNumber(PhoneNumber), keysToFetch:[CNContactGivenNameKey, CNContactFamilyNameKey,CNContactImageData])

  return FirstName, GivenName,UIImage

 }

J'ai l'impression que je vais à ce sujet à l'envers mais je ne suis pas sûr de la voie à suivre. Des idées?

9
Mathew Jenkinson

Afin d’obtenir rapidement cet exemple opérationnel, j’ai utilisé les sources d’informations suivantes:

Filtrer les non-chiffres de la chaîne

https://stackoverflow.com/a/32700339/558933

http://www.appcoda.com/ios-contacts-framework/

Le bloc de code ci-dessous inclut le contrôle d'autorisation car je devais le faire fonctionner pour pouvoir tester dans le simulateur. Le code est juste le contrôleur de vue Single-View Apps et vous pouvez connecter une UIButton dans le Storyboard à la méthode findContactInfoForPhoneNumber: pour obtenir si exécuter. La sortie est vers la console - vous devrez remplacer ces instructions print par quelque chose d'autre.

Si le code du contrôleur d'affichage complet ne vous intéresse pas, il suffit de regarder la méthode searchForContactUsingPhoneNumber(phoneNumber: String). J'ai suivi les conseils d'Apple dans la documentation pour exécuter le cadre CNContact de manière asynchrone.

Le code supprime tous les symboles +, - et ( qui pourraient se trouver dans un numéro de téléphone et ne font que correspondre aux chiffres, de sorte que le numéro de téléphone pour lequel vous faites correspondre DOIT être exactement le même.

//
//  ViewController.Swift
//  ContactsTest
//
//  Created by Robotic Cat on 13/04/2016.
//

import UIKit
import Contacts

class ViewController: UIViewController {

    // MARK: - App Logic
    func showMessage(message: String) {
        // Create an Alert
        let alertController = UIAlertController(title: "Alert", message: message, preferredStyle: UIAlertControllerStyle.Alert)

        // Add an OK button to dismiss
        let dismissAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default) { (action) -> Void in
        }
        alertController.addAction(dismissAction)

        // Show the Alert
        self.presentViewController(alertController, animated: true, completion: nil)
    }

    func requestForAccess(completionHandler: (accessGranted: Bool) -> Void) {
        // Get authorization
        let authorizationStatus = CNContactStore.authorizationStatusForEntityType(CNEntityType.Contacts)

        // Find out what access level we have currently
        switch authorizationStatus {
        case .Authorized:
            completionHandler(accessGranted: true)

        case .Denied, .NotDetermined:
            CNContactStore().requestAccessForEntityType(CNEntityType.Contacts, completionHandler: { (access, accessError) -> Void in
                if access {
                    completionHandler(accessGranted: access)
                }
                else {
                    if authorizationStatus == CNAuthorizationStatus.Denied {
                        dispatch_async(dispatch_get_main_queue(), { () -> Void in
                            let message = "\(accessError!.localizedDescription)\n\nPlease allow the app to access your contacts through the Settings."
                            self.showMessage(message)
                        })
                    }
                }
            })

        default:
            completionHandler(accessGranted: false)
        }
    }

    @IBAction func findContactInfoForPhoneNumber(sender: UIButton) {

        self.searchForContactUsingPhoneNumber("(888)555-1212)")
    }

    func searchForContactUsingPhoneNumber(phoneNumber: String) {

        dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), { () -> Void in
            self.requestForAccess { (accessGranted) -> Void in
                if accessGranted {
                    let keys = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactImageDataKey, CNContactPhoneNumbersKey]
                    var contacts = [CNContact]()
                    var message: String!

                    let contactsStore = CNContactStore()
                    do {
                        try contactsStore.enumerateContactsWithFetchRequest(CNContactFetchRequest(keysToFetch: keys)) {
                            (contact, cursor) -> Void in
                            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 {
                                            contacts.append(contact)
                                        }
                                    }
                                }
                            }
                        }

                        if contacts.count == 0 {
                            message = "No contacts were found matching the given phone number."
                        }
                    }
                    catch {
                        message = "Unable to fetch contacts."
                    }

                    if message != nil {
                        dispatch_async(dispatch_get_main_queue(), { () -> Void in
                            self.showMessage(message)
                        })
                    }
                    else {
                        // Success
                        dispatch_async(dispatch_get_main_queue(), { () -> Void in
                            // Do someting with the contacts in the main queue, for example
                            /*
                             self.delegate.didFetchContacts(contacts) <= which extracts the required info and puts it in a tableview
                             */
                            print(contacts) // Will print all contact info for each contact (multiple line is, for example, there are multiple phone numbers or email addresses)
                            let contact = contacts[0] // For just the first contact (if two contacts had the same phone number)
                            print(contact.givenName) // Print the "first" name
                            print(contact.familyName) // Print the "last" name
                            if contact.isKeyAvailable(CNContactImageDataKey) {
                                if let contactImageData = contact.imageData {
                                    print(UIImage(data: contactImageData)) // Print the image set on the contact
                                }
                            } else {
                                // No Image available

                            }
                        })
                    }
                }
            }
        })
    }

}
10
Robotic Cat

ContactList avec ContactUI Framework avec Tableview personnalisé

import UIKit

class ContactCell: UITableViewCell {
    @IBOutlet weak var PersonNameLabel: UILabel!

    @IBOutlet weak var PersonMobileNOLabel: UILabel!

    @IBOutlet weak var PersonImage: UIImageView!

    @IBOutlet weak var PersonEmailLabel: UILabel!
}

ContactViewController

import ContactsUI

class ContactViewController: UIViewController,CNContactPickerDelegate,UITableViewDelegate,UITableViewDataSource{
var objects  = [CNContact]() 
@IBOutlet weak var tableView: UITableView! 
override func viewDidLoad() {
    super.viewDidLoad()
  self.getContacts()
}
func getContacts() {
    let store = CNContactStore()

    switch CNContactStore.authorizationStatus(for: .contacts){
    case .authorized:
        self.retrieveContactsWithStore(store: store)

    // This is the method we will create
    case .notDetermined:
        store.requestAccess(for: .contacts){succeeded, err in
            guard err == nil && succeeded else{
                return
            }
            self.retrieveContactsWithStore(store: store)

        }
    default:
        print("Not handled")
    }

}
func retrieveContactsWithStore(store: CNContactStore)
{


 let keysToFetch = [CNContactFormatter.descriptorForRequiredKeys(for: .fullName), CNContactPhoneNumbersKey,CNContactImageDataKey, CNContactEmailAddressesKey] as [Any]
    let request = CNContactFetchRequest(keysToFetch: keysToFetch as! [CNKeyDescriptor])
    var cnContacts = [CNContact]()
    do {
        try store.enumerateContacts(with: request){
            (contact, cursor) -> Void in
            if (!contact.phoneNumbers.isEmpty) {
            }

            if contact.isKeyAvailable(CNContactImageDataKey) {
                if let contactImageData = contact.imageData {
                    print(UIImage(data: contactImageData)) // Print the image set on the contact
                }
            } else {
                // No Image available

            }
            if (!contact.emailAddresses.isEmpty) {
            }
            cnContacts.append(contact)
             self.objects = cnContacts
        }
    } catch let error {
        NSLog("Fetch contact error: \(error)")
    }

    NSLog(">>>> Contact list:")
    for contact in cnContacts {
        let fullName = CNContactFormatter.string(from: contact, style: .fullName) ?? "No Name"
        NSLog("\(fullName): \(contact.phoneNumbers.description)")
    }
   self.tableView.reloadData()   
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.objects.count
}
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath as IndexPath) as! ContactCell  
    let contact = self.objects[indexPath.row]
print("theis my contact arrau \(self.objects.count)")
    let formatter = CNContactFormatter()  
    cell.PersonNameLabel.text = formatter.string(from: contact )
if let actualNumber = contact.phoneNumbers.first?.value as? CNPhoneNumber {
    //Get the label of the phone number

    //Strip out the stuff you don't need
    print(actualNumber.stringValue)  
cell.PersonMobileNOLabel.text = actualNumber.stringValue
}
else{
    cell.PersonMobileNOLabel.text = "N.A "
}
if let actualEmail = (contact as AnyObject).emailAddresses?.first?.value as String? {
    print(actualEmail)  
    cell.PersonEmailLabel.text = actualEmail
}
else{
    cell.PersonEmailLabel.text = "N.A "
}
if let imageData = contact.imageData {
    //If so create the image
    let userImage = UIImage(data: imageData)
    cell.PersonImage.image = userImage;
}

else{
    cell.PersonImage.image = UIImage (named: "N.A")
}
    return cell
}
}
1
Sahil Puri

La méthode correcte consiste à indexer les numéros de téléphone dans votre propre base de données afin de pouvoir rechercher l'identifiant du contact. 

0
logicu