I need an option like image picker for picking contact and to display phone number i have managed to get contact names using below code
by using this code it only returns the names , need an option to pick contact from contact list
import ContactsUI
and include - CNContactPickerDelegate
import ContactsUI
class YourViewController: CNContactPickerDelegate{
//MARK:- contact picker
func onClickPickContact(){
let contactPicker = CNContactPickerViewController()
contactPicker.delegate = self
contactPicker.displayedPropertyKeys =
[CNContactGivenNameKey
, CNContactPhoneNumbersKey]
self.present(contactPicker, animated: true, completion: nil)
}
func contactPicker(_ picker: CNContactPickerViewController,
didSelect contactProperty: CNContactProperty) {
}
func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) {
// You can fetch selected name and number in the following way
// user name
let userName:String = contact.givenName
// user phone number
let userPhoneNumbers:[CNLabeledValue<CNPhoneNumber>] = contact.phoneNumbers
let firstPhoneNumber:CNPhoneNumber = userPhoneNumbers[0].value
// user phone number string
let primaryPhoneNumberStr:String = firstPhoneNumber.stringValue
print(primaryPhoneNumberStr)
}
func contactPickerDidCancel(_ picker: CNContactPickerViewController) {
}
}
import ContactsUI
private let contactPicker = CNContactPickerViewController()
Button click that initiates contact picker:
@IBAction func accessContacts(_ sender: Any) {
contactPicker.delegate = self
self.present(contactPicker, animated: true, completion: nil)
}
Implement delegate methods
extension YourViewController: CNContactPickerDelegate {
func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) {
let phoneNumberCount = contact.phoneNumbers.count
guard phoneNumberCount > 0 else {
dismiss(animated: true)
//show pop up: "Selected contact does not have a number"
return
}
if phoneNumberCount == 1 {
setNumberFromContact(contactNumber: contact.phoneNumbers[0].value.stringValue)
} else {
let alertController = UIAlertController(title: "Select one of the numbers", message: nil, preferredStyle: .alert)
for i in 0...phoneNumberCount-1 {
let phoneAction = UIAlertAction(title: contact.phoneNumbers[i].value.stringValue, style: .default, handler: {
alert -> Void in
self.setNumberFromContact(contactNumber: contact.phoneNumbers[i].value.stringValue)
})
alertController.addAction(phoneAction)
}
let cancelAction = UIAlertAction(title: "Cancel", style: .destructive, handler: {
alert -> Void in
})
alertController.addAction(cancelAction)
dismiss(animated: true)
self.present(alertController, animated: true, completion: nil)
}
}
func setNumberFromContact(contactNumber: String) {
//UPDATE YOUR NUMBER SELECTION LOGIC AND PERFORM ACTION WITH THE SELECTED NUMBER
var contactNumber = contactNumber.replacingOccurrences(of: "-", with: "")
contactNumber = contactNumber.replacingOccurrences(of: "(", with: "")
contactNumber = contactNumber.replacingOccurrences(of: ")", with: "")
contactNumber = contactNumber.removeWhitespacesInBetween()
guard contactNumber.count >= 10 else {
dismiss(animated: true) {
self.popUpMessageError(value: 10, message: "Selected contact does not have a valid number")
}
return
}
textFieldNumber.text = String(contactNumber.suffix(10))
}
func contactPickerDidCancel(_ picker: CNContactPickerViewController) {
}
}
You can use this extension to get a contact name.
extension CNContact {
open func displayName() -> String {
return givenName + " " + familyName
}
}
This is Class to get Some details EPContact
Swift 5 & Contact Picker Get Email
I wanted to show an example of how you can do the same thing you asked for but for email instead and updated for Swift 5 since some of the answers do not compile correctly above. This also has the added bonus of the 'all' option which will concatenate multiple emails into one string if the user selects it or not.
First make sure to import import ContactsUI
Then make sure you have an outlet to your textfield.
@IBOutlet var emailTextField: UITextField!
Next you need to set the contact picker as a member variable of your viewController. This will hold the information for showing the contact picker later.
class EmailViewController: UIViewController {
@IBOutlet var emailTextField: UITextField!
private let contactPicker = CNContactPickerViewController()
//... rest of view controller code, etc...
}
Finally you can simply add this extension to the EmailViewController with the code below:
extension EmailViewController: CNContactPickerDelegate {
func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) {
let emailNumberCount = contact.emailAddresses.count
//@JA - They have to have at least 1 email address
guard emailNumberCount > 0 else {
dismiss(animated: true)
//show pop up: "Selected contact does not have a number"
let alertController = UIAlertController(title: "No emails found for contact: "+contact.givenName+" "+contact.familyName, message: nil, preferredStyle: .alert)
let cancelAction = UIAlertAction(title: "Ok", style: .default, handler: {
alert -> Void in
})
alertController.addAction(cancelAction)
self.present(alertController, animated: true, completion: nil)
return
}
//@JA - If they have only 1 email it's easy. If there is many emails we want to concatenate them and separate by commas , , ...
if emailNumberCount == 1 {
setEmailFromContact(contactEmail: contact.emailAddresses[0].value as String)
} else {
let alertController = UIAlertController(title: "Select an email from contact: "+contact.givenName+" "+contact.familyName+" or select 'All' to send to every email listed.", message: nil, preferredStyle: .alert)
for i in 0...emailNumberCount-1 {
let emailAction = UIAlertAction(title: contact.emailAddresses[i].value as String, style: .default, handler: {
alert -> Void in
self.setEmailFromContact(contactEmail: contact.emailAddresses[i].value as String)
})
alertController.addAction(emailAction)
}
let allAction = UIAlertAction(title: "All", style: .destructive, handler: {
alert -> Void in
var emailConcat = ""
for i in 0...emailNumberCount-1{
if(i != emailNumberCount-1){ //@JA - Only add the , if we are not on the last item of the array
emailConcat = emailConcat + (contact.emailAddresses[i].value as String)+","
}else{
emailConcat = emailConcat + (contact.emailAddresses[i].value as String)
}
}
self.setEmailFromContact(contactEmail: emailConcat)//@JA - Sends the concatenated version of the emails separated by commas
})
alertController.addAction(allAction)
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: {
alert -> Void in
})
alertController.addAction(cancelAction)
dismiss(animated: true)
self.present(alertController, animated: true, completion: nil)
}
}
func setEmailFromContact(contactEmail: String){
emailTextField.text = contactEmail
}
func contactPickerDidCancel(_ picker: CNContactPickerViewController) {
print("contact picker canceled")
}
}
To call up the picker in the action event of a button for example you could do this:
@IBAction func contactsButtonPressed(_ sender: UIButton) {
contactPicker.delegate = self
self.present(contactPicker, animated: true, completion: nil)
}
contactPicker.delegate = self
works because of the extension on the viewController class (emailViewController) in my case that gives it access to the CNContactPickerDelegate
protocol functions it requires.
If contact have more than one phone numbers, then you can get the selected number by comparing the 'contactProperty.identifier' as below -
public func contactPicker(_ picker: CNContactPickerViewController, didSelect contactProperty: CNContactProperty) {
tvName.text = contactProperty.contact.givenName
var selectedNo = ""
if contactProperty.key == "phoneNumbers" {
contactProperty.contact.phoneNumbers.forEach({ phone in
if phone.identifier == contactProperty.identifier {
selectedNo = phone.value.stringValue
}
})
}
tvContact.text = selectedNo
}
© 2022 - 2024 — McMap. All rights reserved.