How to get the selected contactProperty from CNContactPickerViewController

969 Views Asked by At

I'm currently able to get a contact from the contacts app, but the problem I'm facing that I need to be able to select the contact I want to import to my app , if the contact have more than 1 phone number, I always get the first number, here is the code I'm using:

func contactPicker(_ picker: CNContactPickerViewController, didSelect contactProperty: CNContactProperty) {

    let numbers     = contactProperty.contact.phoneNumbers.first
    let firstName   = contactProperty.contact.givenName
    let lastName    = contactProperty.contact.familyName
    let phoneNumber = (numbers?.value)?.stringValue ?? ""

    /// Duplicate phone numbers will not be saved
    if phoneNumbers.contains(phoneNumber) {
        return
    }
    /// Saving selected contact in Core Data
    CoreDataManager.sharedInstance.savePhoneNumberInCoreData(FirstName: firstName, LastName: lastName, PhoneNumber: phoneNumber)

    DispatchQueue.main.async { [weak self] in
        self?.tableView.reloadData()
    }
}

The problem with line:

contactProperty.contact.phoneNumbers.first

There are two options only for contactProperty.contact.phoneNumbers .first or .last

If there is something like .selected, it would solve the problem.

3

There are 3 best solutions below

6
On BEST ANSWER

There is something called Main telephone number that you could use

var phoneNumber: String?

if let mainNumber = numbers.first(where: { $0.label == CNLabelPhoneNumberMain }) {
    phoneNumber = mainNumber.value.stringValue
} else {
    phoneNumber = numbers.first?.value.stringValue //or some other default value
}

Note that I changed the definition of numbers to be the array of phone numbers

let numbers = contactProperty.contact.phoneNumbers

Full code:

func contactPicker(_ picker: CNContactPickerViewController, didSelect contactProperty: CNContactProperty) {

    let numbers = contactProperty.contact.phoneNumbers    
    var phoneNumber: String?

    if let mainNumber = numbers.first(where: { $0.label == CNLabelPhoneNumberMain }) {
        phoneNumber = mainNumber.value.stringValue
    } else {
        phoneNumber = numbers.first?.value.stringValue //or some other default value
    }

    if phoneNumber == nil || phoneNumbers.contains(phoneNumber) {
        return
    }

    let firstName = contactProperty.contact.givenName
    let lastName = contactProperty.contact.familyName   

    CoreDataManager.sharedInstance.savePhoneNumberInCoreData(FirstName: firstName, LastName: lastName, PhoneNumber: phoneNumber)

    DispatchQueue.main.async { [weak self] in
        self?.tableView.reloadData()
    }
}
0
On

I'm agree with solution of Joakim Danielson.

But there are one more solution to get specific phone number which is stored in mobile number like home, mobile, fax etc.

Get all numbers from contact and enumerate on every number and check labeled values. See following code.

let numbers = contact.phoneNumbers

numbers.forEach { (c) in

    if let label = c.label {

        let localizedLabel = CNLabeledValue<NSCopying & NSSecureCoding>.localizedString(forLabel: label)
        print("\(localizedLabel)")

        switch localizedLabel.lowercased() {

        case "home":
            let homeNumber = c.value
            break

        case "mobile":
            let mobileNumber = c.value
            break

        default:
            break
        }
    }
}
0
On

contactProperty.contacts is a back-reference to the CNContact the selected property lives in...

Each property is represented by an instance of CNContactProperty, which provides a tuple that can contain three or five values, depending on whether the property is a member of an array of labeled values. CNContactProperty

So, you should use the property's Information vars directly:

For example, the phoneNumbers property is a member of an array of labeled values, so the CNContactProperty tuple contains the contact, key, value, identifier, and label.

CNContactProperty

NOTE: I learned this from reading another S-O answer, but I can't seem to find it right now. If appropriate, dupe or edit thus,