Supertecnoboff
Supertecnoboff

Reputation: 6606

Extract email from CNContactProperty - iOS 9

I have an iOS app which needs access to the Contacts picker view controller in order to allow the user to select a contact property such as email address/ telephone numbers of imessage email addresses.

The problem I am having right now, is that I can't figure out how to parse the returned data. I have made use of the contactPicker didSelectContactProperty method, but I am unable to parse the data I need.

-(void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperty:(CNContactProperty *)contactProperty {

   CNLabeledValue *test = contactProperty.contact.emailAddresses.firstObject;
   NSLog(@"%@", test);

   NSLog(@"%@", contactProperty.contact.phoneNumbers);
}

If you run the above code you get the following response:

2015-10-11 13:30:07.059 Actions[516:212765] <CNLabeledValue: 0x13656d090: identifier=21F2B1B2-8158-466B-9224-E2036CA07D28, label=_$!<Other>!$_, [email protected]> 2015-10-11 13:30:07.061 App_Name[516:212765] (
    "<CNLabeledValue: 0x13672a500: identifier=6697A0E9-3B91-4566-B26E-83B87979F816, label=_$!<Main>!$_, value=<CNPhoneNumber: 0x13672a660: countryCode=gb, digits=08000391010>>" )

Thats great, but how do I extract the data I need from it? Why are the NSLog statements returning the data in a weird format?

Thanks for your time, Dan.

Upvotes: 7

Views: 6861

Answers (5)

Mari&#225;n Čern&#253;
Mari&#225;n Čern&#253;

Reputation: 15778

Swift

This is the proper way how to do it:

func contactPicker(_ picker: CNContactPickerViewController, didSelect contactProperty: CNContactProperty) {
    if contactProperty.key == CNContactEmailAddressesKey,
       let emailAddress = contactProperty.value as? String
    {
        print(emailAddress)
    }
}

If you would select contactProperty.contact.emailAddresses.first, you would get the first email address of the contact which might not necessary be the email address the user has selected.

In case you are querying phone numbers, use the following body instead:

if let phoneNumber = contactProperty.value as? CNPhoneNumber {
    print(phoneNumber.stringValue)
}

Upvotes: 2

Chris Loonam
Chris Loonam

Reputation: 5745

The returned values are of the CNLabeledValue class. In order to get the value from them, for, say, the emails, do this

CNLabeledValue *emailValue = contactProperty.contact.emailAddresses.firstObject;
NSString *emailString = emailValue.value;

If the value you wanted a phone number, this is how you would retrieve that

CNLabeledValue *phoneNumberValue = contactProperty.contact.phoneNumbers.firstObject;
CNPhoneNumber *phoneNumber = phoneNumberValue.value;
NSString *phoneNumberString = phoneNumber.stringValue;

Because the returned value is a CNLabeledValue, you are also able to retrieve the phone number's or email's label

NSString *emailLabel = emailValue.label; //This may be 'Work', 'Home', etc.
NSString *phoneNumberLabel = phoneNumberValue.label;

Upvotes: 15

James Wolfe
James Wolfe

Reputation: 360

Unfortunately Chris' answer tells you how to get the value from the CNLabeledValue object that is returned, but it doesn't tell you how to identify what CNLabeledValue was selected based on the contactProperty parameter the function features.

What you need to do is cycle through each of the contact's email addresses and check if it's identifier matches up with the selected contactProperty identifier. Use the following code inside the didSelectContactProperty function:

NSString *selectedEmail;

for (CNLabeledValue<NSString*>* email in contactProperty.contact.emailAddresses) {
    if ([email.identifier isEqualToString:contactProperty.identifier]) {
            selectedEmail = (NSString *)email.value;
    }
}

Note I have only tested this code with postal addresses, so it may require some further tweaking to work with email addresses.

Upvotes: 1

guru
guru

Reputation: 2817

For swift 3.0 :

 public func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact)
{
      if let emailValue : CNLabeledValue = contact.emailAddresses.first
    {
        txtEmail.text = emailValue.value as String
    }
    if let phoneNumber : CNLabeledValue = contact.phoneNumbers.first
    {
        txtMobno.text = phoneNumber.value.stringValue
    }
     txtFname.text = contact.givenName + " " + contact.familyName

}

Upvotes: 1

guru
guru

Reputation: 2817

Here is swift version of Chris answer :

 func fatchContacts(store : CNContactStore)  {
    do
    {
    let groups = try store.groups(matching: nil)
    let predicate =  CNContact.predicateForContactsInGroup(withIdentifier: groups[0].identifier)
    //let predicate = CNContact.predicateForContactsMatchingName("John")
        let keyToFatch = [CNContactFormatter.descriptorForRequiredKeys(for: .fullName ) ,CNContactEmailAddressesKey] as [Any]
    let contacts = try store.unifiedContacts(matching: predicate, keysToFetch: keyToFatch as! [CNKeyDescriptor])            //------------------------------------------------------
   //-------------Get Here-----------------------------------------
     print(contacts)
     print(contacts[0])
        let formatter = CNContactFormatter ()
        print(formatter.string(from: contacts[0]))
        print(contacts[0].givenName)
        print(contacts[0].emailAddresses)
        let emailValue : CNLabeledValue = contacts[0].emailAddresses.first!;
        let  email = emailValue.value
        print(email)




    }
    catch{

    }
}


Just pass the CNContactStore object        

Upvotes: 0

Related Questions