Reputation: 6606
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
Reputation: 15778
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
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
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
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
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