私のコードがSwiftでコンパイルできない理由がわかりません。
私はこのObjective-Cコードを変換しようとしています:
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
if (addressBook != nil) {
NSLog(@"Succesful.");
NSArray *allContacts = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
}
これは私の現在のSwiftでの表現です:
var error:CFErrorRef
var addressBook = ABAddressBookCreateWithOptions(nil, nil);
if (addressBook != nil) {
println("Succesful.");
var allContacts:CFArrayRef = ABAddressBookCopyArrayOfAllPeople(addressBook);
}
しかし、Xcodeは次のように報告します。
「管理対象外」は「CFArrayRef」に変換できません
アイデアはありますか?
明らかに、iOSバージョン9以降をターゲットにしている場合は、AddressBook
フレームワークをまったく使用せず、代わりにContacts
フレームワークを使用してください。
そう、
インポートContacts
:
import Contacts
Info.plist
には必ずNSContactsUsageDescription
を指定してください。
その後、連絡先にアクセスできます。例えば。 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
}
}