Ответ 1
Очевидно, что если таргетинг на iOS версии 9 или выше, вы не должны использовать структуру AddressBook
вообще, а вместо этого вместо этого используйте фреймворк Contacts
.
Итак,
-
Импорт
Contacts
:import Contacts
-
Обязательно поставьте
NSContactsUsageDescription
в свойInfo.plist
. -
Затем вы можете получить доступ к контактам. Например. в Swift 3:
let status = CNContactStore.authorizationStatus(for: .contacts) if status == .denied || status == .restricted { presentSettingsActionSheet() return } // open it let store = CNContactStore() store.requestAccess(for: .contacts) { granted, error in guard granted else { DispatchQueue.main.async { self.presentSettingsActionSheet() } return } // get the contacts var contacts = [CNContact]() let request = CNContactFetchRequest(keysToFetch: [CNContactIdentifierKey as NSString, CNContactFormatter.descriptorForRequiredKeys(for: .fullName)]) do { try store.enumerateContacts(with: request) { contact, stop in contacts.append(contact) } } catch { print(error) } // do something with the contacts array (e.g. print the names) let formatter = CNContactFormatter() formatter.style = .fullName for contact in contacts { print(formatter.string(from: contact) ?? "???") } }
Где
func presentSettingsActionSheet() { let alert = UIAlertController(title: "Permission to Contacts", message: "This app needs access to contacts in order to ...", preferredStyle: .actionSheet) alert.addAction(UIAlertAction(title: "Go to Settings", style: .default) { _ in let url = URL(string: UIApplicationOpenSettingsURLString)! UIApplication.shared.open(url) }) alert.addAction(UIAlertAction(title: "Cancel", style: .cancel)) present(alert, animated: true) }
Мой оригинальный ответ для структуры AddressBook ниже.
Несколько наблюдений:
-
Если вы хотите использовать
error
параметрABAddressBookCreateWithOptions
, определите его какUnmanaged<CFError>?
. -
Если это не удается, посмотрите на объект ошибки (сделав
takeRetainedValue
, чтобы вы не просочились). -
Обязательно
takeRetainedValue
адресной книги, чтобы вы не просочились. -
Вы, вероятно, не должны просто захватывать контакты, но сначала вы должны сначала запросить разрешение.
Вытащить все вместе:
// make sure user hadn't previously denied access
let status = ABAddressBookGetAuthorizationStatus()
if status == .Denied || status == .Restricted {
// user previously denied, so tell them to fix that in settings
return
}
// open it
var error: Unmanaged<CFError>?
guard let addressBook: ABAddressBook? = ABAddressBookCreateWithOptions(nil, &error)?.takeRetainedValue() else {
print(error?.takeRetainedValue())
return
}
// request permission to use it
ABAddressBookRequestAccessWithCompletion(addressBook) { granted, error in
if !granted {
// warn the user that because they just denied permission, this functionality won't work
// also let them know that they have to fix this in settings
return
}
if let people = ABAddressBookCopyArrayOfAllPeople(addressBook)?.takeRetainedValue() as? NSArray {
// now do something with the array of people
}
}