我试图写一个简单的方法,要求用户访问他们的通讯录,然后打印出通讯录中每个人的名字。我已经看到了一些教程解释如何在objective-C,但我有一个很难将它们转换为swift。
这是我到目前为止做的。下面的块运行在我的viewDidLoad()方法中,并检查用户是否已经授权访问通讯录,如果他们还没有授权访问,第一个if语句将要求访问。此部分按预期工作。
var emptyDictionary: CFDictionaryRef?
var addressBook: ABAddressBookRef?
if (ABAddressBookGetAuthorizationStatus() == ABAuthorizationStatus.NotDetermined)
{
println("requesting access...")
addressBook = !ABAddressBookCreateWithOptions(emptyDictionary,nil)
ABAddressBookRequestAccessWithCompletion(addressBook,{success,error in
if success {
self.getContactNames();
}
else
{
println("error")
}
})
}
}
else if (ABAddressBookGetAuthorizationStatus() == ABAuthorizationStatus.Denied || ABAddressBookGetAuthorizationStatus() == ABAuthorizationStatus.Restricted)
{
println("access denied")
}
else if (ABAddressBookGetAuthorizationStatus() == ABAuthorizationStatus.Authorized)
{
println("access granted")
getContactNames()
}
一旦我知道用户已授予访问权限,我运行getContactNames()方法如下。经过多次来回,我最终能够通过添加takeRetainedValue()方法来获得这个编译,以便将ABAddressBookcopyArrayOfAllPeople返回的数组从非托管数组转换为托管数组,然后允许我将CFArrayRef转换为NSArray。
我遇到的问题是,contactList数组的计数结果为0,因此for循环被跳过。在我的模拟器中,地址簿有6或7条记录,所以我希望数组具有这样的长度。有任何想法吗?
func getContactNames()
{
addressBook = !ABAddressBookCreateWithOptions(emptyDictionary,nil)
var contactList: NSArray = ABAddressBookcopyArrayOfAllPeople(addressBook).takeRetainedValue()
println("records in the array \(contactList.count)") // returns 0
for record:ABRecordRef in contactList {
var contactPerson: ABRecordRef = record
var contactName: String = ABRecordCopycompositeName(contactPerson).takeRetainedValue()
println ("contactName \(contactName)")
}
}
另外一点 – 如果我使用ABAddressBookGetPersonCount方法,它返回-1。
var count: CFIndex = ABAddressBookGetPersonCount(addressBook);
println("records in the array \(count)") // returns -1
基于这个链接ABAddressBookGetPersonCount returns -1 in iOS,似乎这个函数返回-1可能与权限未被授予相关,但我绝对已经在上面的代码请求权限(并在我在模拟器中运行应用程序时授予它)
这现在更简单了。要注意的主要事情是,如果你没有授权创建一个ABAddressBook,你会得到一个邪恶的地址簿 – 它不是零,但它也不是好的任何东西。以下是我目前建议您设置授权状态并在必要时请求授权的方法:
var adbk : ABAddressBook!
func createAddressBook() -> Bool {
if self.adbk != nil {
return true
}
var err : Unmanaged<CFError>? = nil
let adbk : ABAddressBook? = ABAddressBookCreateWithOptions(nil,&err).takeRetainedValue()
if adbk == nil {
println(err)
self.adbk = nil
return false
}
self.adbk = adbk
return true
}
func determineStatus() -> Bool {
let status = ABAddressBookGetAuthorizationStatus()
switch status {
case .Authorized:
return self.createAddressBook()
case .NotDetermined:
var ok = false
ABAddressBookRequestAccessWithCompletion(nil) {
(granted:Bool,err:CFError!) in
dispatch_async(dispatch_get_main_queue()) {
if granted {
ok = self.createAddressBook()
}
}
}
if ok == true {
return true
}
self.adbk = nil
return false
case .Restricted:
self.adbk = nil
return false
case .Denied:
self.adbk = nil
return false
}
}
下面是如何遍历所有人,并打印出他们的名字:
func getContactNames() {
if !self.determineStatus() {
println("not authorized")
return
}
let people = ABAddressBookcopyArrayOfAllPeople(adbk).takeRetainedValue() as NSArray as [ABRecord]
for person in people {
println(ABRecordCopycompositeName(person).takeRetainedValue())
}
}