I have an API that returns phone numbers in format: +1415xxxxxxx (E164)
Right now these numbers are put into a Cell of a UITableView and are presented as expected, however I'd like to be able to search the users contacts on the phone to see if the there is a match - if so also pass back the Firstname, last name and known photo.
Looking at the Apple pages (https://developer.apple.com/library/watchos/documentation/Contacts/Reference/Contacts_Framework/index.html) I need to
import ContactsUI
but then Im unsure, do I load the contactDB into a dictionary and then search it? I can find lots of things on searching via name and less on searching via number:
let predicate = CNContact.predicateForContactsMatchingName("Sam")
Im trying to get to a function that I can call, that searches using the PhoneNumber and gives me back the FirstName, FamilyName and Image.
func searchForContactUsingNumber(PhoneNumber: String)
{
// Search Via phoneNumber
let store = CNContactStore()
let contacts = try store.unifiedContactsMatchingPredicate(CNContact.predicateForContactsMatchingPhoneNumber(PhoneNumber), keysToFetch:[CNContactGivenNameKey, CNContactFamilyNameKey,CNContactImageData])
return FirstName, GivenName,UIImage
}
I get the feeling I'm going about this backwards but not sure which way is forwards.. Any ideas?
import UIKit import Contacts
class PhonebookVC: UIViewController ,UITableViewDataSource,UITableViewDelegate {
@IBOutlet weak var ContactTblView: UITableView!
@IBOutlet weak var SearchTxtField: SkyFloatingLabelTextField!
var contacts = [CNContact]()
var NameArray = [String]()
var NumberArray = [String]()
var filteredName = [String]()
var filteredNumber = [String]()
override func viewDidLoad() {
super.viewDidLoad()
getContacts()
SearchTxtField.delegate = self
// Do any additional setup after loading the view.
}
@IBAction func SearchFunc(_ sender: UIButton) {
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.filteredName.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = ContactTblView.dequeueReusableCell(withIdentifier: "cell") as! PhonebookCell
cell.ContactName.text = self.filteredName[indexPath.row]
cell.ContactNumber.text = self.filteredNumber[indexPath.row]
return cell
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}
extension PhonebookVC {
func getContacts()
{
let status = CNContactStore.authorizationStatus(for: .contacts)
if status == .denied || status == .restricted {
presentSettingsActionSheet()
return
}
// open it
let contactStore = CNContactStore()
contactStore.requestAccess(for: .contacts) { granted, error in
guard granted else {
DispatchQueue.main.async {
self.presentSettingsActionSheet()
}
return
}
// get the contacts
let keys = [
CNContactFormatter.descriptorForRequiredKeys(for: .fullName),
CNContactPhoneNumbersKey as CNKeyDescriptor] as [Any]
let request = CNContactFetchRequest(keysToFetch: keys as! [CNKeyDescriptor])
do {
try contactStore.enumerateContacts(with: request){
(contact, stop) in
// Array containing all unified contacts from everywhere
self.contacts.append(contact)
var i = 0
for phoneNumber in contact.phoneNumbers {
print("\(contact.givenName) \(contact.familyName)\n \(phoneNumber.value.stringValue)")
self.NameArray.append("\(contact.givenName) \(contact.familyName)")
self.NumberArray.append(phoneNumber.value.stringValue)
i = i+1
}
i = 0
self.filteredName = self.NameArray
self.filteredNumber = self.NumberArray
self.ContactTblView.reloadData()
}
} catch {
print("unable to fetch contacts")
}
}
}
func presentSettingsActionSheet() {
let alert = UIAlertController(title: "Permission to Contacts", message: "This app needs access to contacts in order to Send top-up.", preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "Go to Settings", style: .default) { _ in
let url = URL(string: UIApplication.openSettingsURLString)!
UIApplication.shared.open(url)
})
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
present(alert, animated: true)
}
}
extension PhonebookVC : UITextFieldDelegate { func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { self.filteredName.removeAll() self.filteredNumber.removeAll()
if(self.NameArray.count != 0){
var mystring = "\(textField.text ?? "")\(string)"
if(textField.text?.count == 1 && string == ""){
mystring = ""
}
var i = 0
for ContactName in self.NameArray {
let name = ContactName
let range = name.lowercased().range(of: mystring, options: .caseInsensitive, range: nil, locale: nil)
if range != nil {
if(filteredName.count == 0){
filteredName = [ContactName]
filteredNumber = [NumberArray[i]]
}else{
filteredName.append(ContactName)
filteredNumber.append(NumberArray[i])
}
}
i = i+1
}
if(string == "" && (textField.text?.count == 1)){
self.filteredName = self.NameArray
self.filteredNumber = self.NumberArray
}
self.ContactTblView.reloadData()
}
return true
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With