¿Cómo accede a un número de teléfono de los contactos de su usuario de manera rápida?

Aquí está mi código para get el nombre de un contacto, ¿cómo obtendré su número de teléfono?

func createAddressBook() -> Bool { if self.addressBook != nil { return true } var err : Unmanaged<CFError>? = nil let addressBook : ABAddressBook? = ABAddressBookCreateWithOptions(nil, &err).takeRetainedValue() if addressBook == nil { println(err) self.addressBook = nil return false } self.addressBook = addressBook getContactNames() return true } func getContactNames() { if !self.determineStatus() { println("not authorized") return } let people = ABAddressBookCopyArrayOfAllPeople(addressBook).takeRetainedValue() as NSArray as [ABRecord] for person in people { var contactName = ABRecordCopyCompositeName(person).takeRetainedValue() as String self.contacts.append(contact(name: contactName)) } } 

Cualquier ayuda sería muy apreciada.

A partir de iOS 9, utilizaríamos el marco de contactos, en el que phoneNumbers es un CNLabeledValue<CNPhoneNumber> :

 let status = CNContactStore.authorizationStatus(for: .contacts) if status == .denied || status == .restricted { presentSettingsAlert() return } // open it let store = CNContactStore() store.requestAccess(for: .contacts) { granted, error in guard granted else { self.presentSettingsAlert() return } // get the contacts let request = CNContactFetchRequest(keysToFetch: [CNContactFormatter.descriptorForRequinetworkingKeys(for: .fullName), CNContactPhoneNumbersKey as CNKeyDescriptor]) do { try store.enumerateContacts(with: request) { contact, stop in let name = CNContactFormatter.string(from: contact, style: .fullName) print(name) for phone in contact.phoneNumbers { var label = phone.label if label != nil { label = CNLabeledValue<CNPhoneNumber>.localizedString(forLabel: label!) } print(" ", label, phone.value.stringValue) } } } catch { print(error) } } 

Dónde

 private func presentSettingsAlert() { let settingsURL = URL(string: UIApplicationOpenSettingsURLString)! DispatchQueue.main.async { let alert = UIAlertController(title: "Permission to Contacts", message: "This app needs access to contacts in order to ...", prefernetworkingStyle: .alert) alert.addAction(UIAlertAction(title: "Go to Settings", style: .default) { _ in UIApplication.shanetworking.openURL(settingsURL) }) alert.addAction(UIAlertAction(title: "Cancel", style: .cancel)) self.present(alert, animated: true) } } 

Antes de iOS 9, usaría el marco de contactos, en el cual los numbers de teléfono son ABMultiValueRef , así que obtenga esa reference y luego repita los numbers de teléfono:

 // make sure user hadn't previously denied access let status = ABAddressBookGetAuthorizationStatus() if status == .denied || status == .restricted { presentSettingsAlert() return } // open it var error: Unmanaged<CFError>? guard let addressBook: ABAddressBook? = ABAddressBookCreateWithOptions(nil, &error)?.takeRetainedValue() else { print(String(describing: error?.takeRetainedValue())) return } // request permission to use it ABAddressBookRequestAccessWithCompletion(addressBook) { granted, error in if !granted { self.presentSettingsAlert() return } guard let people = ABAddressBookCopyArrayOfAllPeople(addressBook)?.takeRetainedValue() as [ABRecord]? else { print("unable to get contacts") return } for person in people { let name = ABRecordCopyCompositeName(person)?.takeRetainedValue() as String? print(name) if let phoneNumbers: ABMultiValue = ABRecordCopyValue(person, kABPersonPhoneProperty)?.takeRetainedValue() { for index in 0 ..< ABMultiValueGetCount(phoneNumbers) { let number = ABMultiValueCopyValueAtIndex(phoneNumbers, index)?.takeRetainedValue() as? String let label = ABMultiValueCopyLabelAtIndex(phoneNumbers, index)?.takeRetainedValue() print(" ", self.localizedLabel(label), number) } } } } 

MacOS tiene una rutina existente para localizar esa label, pero no conozco ninguna function pública en el framework de AddressBook para iOS, por lo que puede convertirla usted mismo (o completar la tabla de localización para NSLocalizedString ):

 // frankly, you probably should just use `NSLocalizedString()` and fill the table with these values private func localizedLabel(_ label: CFString?) -> String? { guard let label = label else { return nil } if CFStringCompare(label, kABHomeLabel, []) == .compareEqualTo { // use `[]` for options in Swift 2.0 return "Home" } else if CFStringCompare(label, kABWorkLabel, []) == .compareEqualTo { return "Work" } else if CFStringCompare(label, kABOtherLabel, []) == .compareEqualTo { return "Other" } else if CFStringCompare(label, kABPersonPhoneMobileLabel, []) == .compareEqualTo { return "Mobile" } else if CFStringCompare(label, kABPersonPhoneIPhoneLabel, []) == .compareEqualTo { return "iPhone" } else if CFStringCompare(label, kABPersonPhoneMainLabel, []) == .compareEqualTo { return "Main" } else if CFStringCompare(label, kABPersonPhoneHomeFAXLabel, []) == .compareEqualTo { return "Home fax" } else if CFStringCompare(label, kABPersonPhoneWorkFAXLabel, []) == .compareEqualTo { return "Work fax" } else if CFStringCompare(label, kABPersonPhoneOtherFAXLabel, []) == .compareEqualTo { return "Other fax" } else if CFStringCompare(label, kABPersonPhonePagerLabel, []) == .compareEqualTo { return "Pager" } else { return label as String } } 

Para Swift 2, ver la revisión previa de esta respuesta .