我试图写一个简单的方法,要求用户访问他们的通讯录,然后打印出通讯录中每个人的名字。我已经看到了一些教程解释如何在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()) } }