我不明白为什么我的代码不能用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报道:
'Unmanaged'不能转换为'CFArrayRef'
你们有个主意吗?
答案 0 :(得分:30)
显然,如果定位到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
的{{1}}参数,请将其定义为ABAddressBookCreateWithOptions
。
如果失败,请查看错误对象(执行Unmanaged<CFError>?
,以免泄漏)。
确保地址簿的takeRetainedValue
也一样,所以不要泄密。
您可能不应该只是抓住联系人,但您可能应首先请求许可。
将所有内容拉到一起得到:
takeRetainedValue