How to select a contact with ABPeoplePickerNavigationController in Swift?

user3745888 picture user3745888 · Aug 9, 2014 · Viewed 16.4k times · Source

I have added the ABPeoplePickerNavigationController into my first view controller. I want that when I select a contact show the info to show in other view controller, but I'm trying use my code and this not show never when I click in a contact. This only open the contact into native app ABPeoplePickerNavigationController.

var people = ABPeoplePickerNavigationController()
var addressBook: ABAddressBookRef?

func extractABAddressBookRef(abRef: Unmanaged<ABAddressBookRef>!) -> ABAddressBookRef? {
    if let ab = abRef {
        self.view.addSubview(people.view)
        return Unmanaged<NSObject>.fromOpaque(ab.toOpaque()).takeUnretainedValue()
    }
    return nil
}

I tried this function

func peoplePickerNavigationController(peoplePicker: ABPeoplePickerNavigationController!,didSelectPerson person: ABRecordRef!) {

    var unmanagedEmails = ABRecordCopyValue(people, kABPersonEmailProperty)
    let emailObj: ABMultiValueRef = Unmanaged.fromOpaque(unmanagedEmails.toOpaque()).takeUnretainedValue() as NSObject as ABMultiValueRef

    var index = 0 as CFIndex

    var unmanagedEmail = ABMultiValueCopyValueAtIndex(emailObj, index)
    var emailAddress:String = Unmanaged.fromOpaque(unmanagedEmail.toOpaque()).takeUnretainedValue() as NSObject as String

    println(emailAddress)      
}

Thanks!

Answer

Jon Vogel picture Jon Vogel · Jul 31, 2015

Here is the latest framework for iOS 9 - ContactsUI

  1. import ContactsUI

  2. Conform to the CNContactPickerDelegate (No required methods)

  3. Create a contacts picker object and present it:

    let peoplePicker = CNContactPickerViewController()
    
    peoplePicker.delegate = self
    
    self.presentViewController(peoplePicker, animated: true, completion: nil)
    
  4. Dismiss the CNContactPickerViewController in the contactPickerDidCancel delegate function

    func contactPickerDidCancel(picker: CNContactPickerViewController) {
        picker.dismissViewControllerAnimated(true, completion: nil)
    }
    
  5. Here is how I Accessed a contacts name, phone numbers, phone number labels, and photo using the didSelectContact delegate function:

    func contactPicker(picker: CNContactPickerViewController, didSelectContact contact: CNContact) {
    //Dismiss the picker VC
    picker.dismissViewControllerAnimated(true, completion: nil)
    //See if the contact has multiple phone numbers
    if contact.phoneNumbers.count > 1 {
        //If so we need the user to select which phone number we want them to use
        let multiplePhoneNumbersAlert = UIAlertController(title: "Which one?", message: "This contact has multiple phone numbers, which one did you want use?", preferredStyle: UIAlertControllerStyle.Alert)
        //Loop through all the phone numbers that we got back
        for number in contact.phoneNumbers {
            //Each object in the phone numbers array has a value property that is a CNPhoneNumber object, Make sure we can get that
            if let actualNumber = number.value as? CNPhoneNumber {
                //Get the label for the phone number
                var phoneNumberLabel = number.label
                //Strip off all the extra crap that comes through in that label
                phoneNumberLabel = phoneNumberLabel.stringByReplacingOccurrencesOfString("_", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
                phoneNumberLabel = phoneNumberLabel.stringByReplacingOccurrencesOfString("$", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
                phoneNumberLabel = phoneNumberLabel.stringByReplacingOccurrencesOfString("!", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
                phoneNumberLabel = phoneNumberLabel.stringByReplacingOccurrencesOfString("<", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
                phoneNumberLabel = phoneNumberLabel.stringByReplacingOccurrencesOfString(">", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
                //Create a title for the action for the UIAlertVC that we display to the user to pick phone numbers
                let actionTitle = phoneNumberLabel + " - " + actualNumber.stringValue
                //Create the alert action
                let numberAction = UIAlertAction(title: actionTitle, style: UIAlertActionStyle.Default, handler: { (theAction) -> Void in
                    //Create an empty string for the contacts name
                    var nameToSave = ""
                    //See if we can get A frist name
                    if contact.givenName == "" {
                        //If Not check for a last name
                        if contact.familyName == "" {
                            //If no last name set name to Unknown Name
                            nameToSave = "Unknown Name"
                        }else{
                            nameToSave = contact.familyName
                        }
                    }else{
                        nameToSave = contact.givenName
                    }
    
                    // See if we can get image data
                    if let imageData = contact.imageData {
                        //If so create the image
                        let userImage = UIImage(data: imageData)
                    }
                    //Do what you need to do with your new contact information here!
                    //Get the string value of the phone number like this:
                    actualNumber.stringValue  
                })
                //Add the action to the AlertController
                multiplePhoneNumbersAlert.addAction(numberAction)
            }
        }
        //Add a cancel action
        let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: { (theAction) -> Void in
            //Cancel action completion
        })
        //Add the cancel action
        multiplePhoneNumbersAlert.addAction(cancelAction)
        //Present the ALert controller
        self.presentViewController(multiplePhoneNumbersAlert, animated: true, completion: nil)
    }else{
        //Make sure we have at least one phone number
        if contact.phoneNumbers.count > 0 {
            //If so get the CNPhoneNumber object from the first item in the array of phone numbers
            if let actualNumber = contact.phoneNumbers.first?.value as? CNPhoneNumber {
                //Get the label of the phone number
                var phoneNumberLabel = contact.phoneNumbers.first!.label
                //Strip out the stuff you don't need
                phoneNumberLabel = phoneNumberLabel.stringByReplacingOccurrencesOfString("_", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
                phoneNumberLabel = phoneNumberLabel.stringByReplacingOccurrencesOfString("$", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
                phoneNumberLabel = phoneNumberLabel.stringByReplacingOccurrencesOfString("!", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
                phoneNumberLabel = phoneNumberLabel.stringByReplacingOccurrencesOfString("<", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
                phoneNumberLabel = phoneNumberLabel.stringByReplacingOccurrencesOfString(">", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
    
                //Create an empty string for the contacts name
                var nameToSave = ""
                //See if we can get A frist name
                if contact.givenName == "" {
                    //If Not check for a last name
                    if contact.familyName == "" {
                        //If no last name set name to Unknown Name
                        nameToSave = "Unknown Name"
                    }else{
                        nameToSave = contact.familyName
                    }
                }else{
                    nameToSave = contact.givenName
                }
    
                // See if we can get image data
                if let imageData = contact.imageData {
                    //If so create the image
                    let userImage = UIImage(data: imageData)
                }
                //Do what you need to do with your new contact information here!
                //Get the string value of the phone number like this:
                actualNumber.stringValue
            }
        }else{
            //If there are no phone numbers associated with the contact I call a custom funciton I wrote that lets me display an alert Controller to the user
            self.displayAlert("Missing info", message: "You have no phone numbers associated with this contact")
        }
    }
    }