use*_*648 45 abaddressbook ios swift
我正在尝试编写一种简单的方法来要求用户访问他们的地址簿,然后在地址簿中打印出每个人的姓名.我已经看过一些教程,解释了如何在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()
}
Run Code Online (Sandbox Code Playgroud)
一旦我知道用户已授予访问权限,我就运行下面的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)")
}
}
Run Code Online (Sandbox Code Playgroud)
还有一点 - 如果我使用ABAddressBookGetPersonCount方法,它返回-1.
var count: CFIndex = ABAddressBookGetPersonCount(addressBook);
println("records in the array \(count)") // returns -1
Run Code Online (Sandbox Code Playgroud)
基于此链接ABAddressBookGetPersonCount在iOS中返回-1,似乎此函数返回-1可能与未授予权限相关,但我肯定已经在上面的代码中请求了权限(并在我运行应用程序时授予它模拟器)
mat*_*att 27
现在这简单得多了.需要注意的首要事项是,如果你在未经授权的情况下创建一个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
}
}
Run Code Online (Sandbox Code Playgroud)
以下是如何循环所有人并打印出他们的名字:
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())
}
}
Run Code Online (Sandbox Code Playgroud)
Wes*_*gne 15
似乎有一个错误的编译器或框架在哪里ABAddressBookRef被声明为typealias AnyObject,但它需要是NSObject为了从Unmanaged<ABAddressBookRef>!返回的包装中解包它ABAddressBookCreateWithOptions.解决方法是将其转换为不透明的C指针.下面的代码可以工作,但它可能应该进行更多的错误检查(并且可能有更好的解决此问题的方法):
var addressBook: ABAddressBookRef?
func extractABAddressBookRef(abRef: Unmanaged<ABAddressBookRef>!) -> ABAddressBookRef? {
if let ab = abRef {
return Unmanaged<NSObject>.fromOpaque(ab.toOpaque()).takeUnretainedValue()
}
return nil
}
func test() {
if (ABAddressBookGetAuthorizationStatus() == ABAuthorizationStatus.NotDetermined) {
println("requesting access...")
var errorRef: Unmanaged<CFError>? = nil
addressBook = extractABAddressBookRef(ABAddressBookCreateWithOptions(nil, &errorRef))
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")
self.getContactNames()
}
}
func getContactNames() {
var errorRef: Unmanaged<CFError>?
addressBook = extractABAddressBookRef(ABAddressBookCreateWithOptions(nil, &errorRef))
var contactList: NSArray = ABAddressBookCopyArrayOfAllPeople(addressBook).takeRetainedValue()
println("records in the array \(contactList.count)")
for record:ABRecordRef in contactList {
var contactPerson: ABRecordRef = record
var contactName: String = ABRecordCopyCompositeName(contactPerson).takeRetainedValue() as NSString
println ("contactName \(contactName)")
}
}
Run Code Online (Sandbox Code Playgroud)
对于那些寻找完整工作解决方案的人来说,这里是如何只打印联系人名称,修改上述代码.调用getAddressBookNames()以访问地址簿,例如在viewDidLoad()方法中.
func getAddressBookNames() {
let authorizationStatus = ABAddressBookGetAuthorizationStatus()
if (authorizationStatus == ABAuthorizationStatus.NotDetermined)
{
NSLog("requesting access...")
var emptyDictionary: CFDictionaryRef?
var addressBook = !ABAddressBookCreateWithOptions(emptyDictionary, nil)
ABAddressBookRequestAccessWithCompletion(addressBook,{success, error in
if success {
self.getContactNames();
}
else {
NSLog("unable to request access")
}
})
}
else if (authorizationStatus == ABAuthorizationStatus.Denied || authorizationStatus == ABAuthorizationStatus.Restricted) {
NSLog("access denied")
}
else if (authorizationStatus == ABAuthorizationStatus.Authorized) {
NSLog("access granted")
getContactNames()
}
}
func getContactNames()
{
var errorRef: Unmanaged<CFError>?
var addressBook: ABAddressBookRef? = extractABAddressBookRef(ABAddressBookCreateWithOptions(nil, &errorRef))
var contactList: NSArray = ABAddressBookCopyArrayOfAllPeople(addressBook).takeRetainedValue()
println("number of contacts: \(contactList.count)")
for record:ABRecordRef in contactList {
var contactName: String = ABRecordCopyCompositeName(record).takeRetainedValue() as NSString
NSLog("contactName: \(contactName)")
}
}
func extractABAddressBookRef(abRef: Unmanaged<ABAddressBookRef>!) -> ABAddressBookRef? {
if let ab = abRef {
return Unmanaged<NSObject>.fromOpaque(ab.toOpaque()).takeUnretainedValue()
}
return nil
}
Run Code Online (Sandbox Code Playgroud)
以下是访问联系人姓名和电子邮件的完整代码- 这是使用其他一些答案中定义的帮助程序方法完成的.
func getAddressBookNames() {
let authorizationStatus = ABAddressBookGetAuthorizationStatus()
if (authorizationStatus == ABAuthorizationStatus.NotDetermined)
{
NSLog("requesting access...")
var emptyDictionary: CFDictionaryRef?
var addressBook = !ABAddressBookCreateWithOptions(emptyDictionary, nil)
ABAddressBookRequestAccessWithCompletion(addressBook,{success, error in
if success {
self.processContactNames();
}
else {
NSLog("unable to request access")
}
})
}
else if (authorizationStatus == ABAuthorizationStatus.Denied || authorizationStatus == ABAuthorizationStatus.Restricted) {
NSLog("access denied")
}
else if (authorizationStatus == ABAuthorizationStatus.Authorized) {
NSLog("access granted")
processContactNames()
}
}
func processContactNames()
{
var errorRef: Unmanaged<CFError>?
var addressBook: ABAddressBookRef? = extractABAddressBookRef(ABAddressBookCreateWithOptions(nil, &errorRef))
var contactList: NSArray = ABAddressBookCopyArrayOfAllPeople(addressBook).takeRetainedValue()
println("records in the array \(contactList.count)")
for record:ABRecordRef in contactList {
processAddressbookRecord(record)
}
}
func processAddressbookRecord(addressBookRecord: ABRecordRef) {
var contactName: String = ABRecordCopyCompositeName(addressBookRecord).takeRetainedValue() as NSString
NSLog("contactName: \(contactName)")
processEmail(addressBookRecord)
}
func processEmail(addressBookRecord: ABRecordRef) {
let emailArray:ABMultiValueRef = extractABEmailRef(ABRecordCopyValue(addressBookRecord, kABPersonEmailProperty))!
for (var j = 0; j < ABMultiValueGetCount(emailArray); ++j) {
var emailAdd = ABMultiValueCopyValueAtIndex(emailArray, j)
var myString = extractABEmailAddress(emailAdd)
NSLog("email: \(myString!)")
}
}
func extractABAddressBookRef(abRef: Unmanaged<ABAddressBookRef>!) -> ABAddressBookRef? {
if let ab = abRef {
return Unmanaged<NSObject>.fromOpaque(ab.toOpaque()).takeUnretainedValue()
}
return nil
}
func extractABEmailRef (abEmailRef: Unmanaged<ABMultiValueRef>!) -> ABMultiValueRef? {
if let ab = abEmailRef {
return Unmanaged<NSObject>.fromOpaque(ab.toOpaque()).takeUnretainedValue()
}
return nil
}
func extractABEmailAddress (abEmailAddress: Unmanaged<AnyObject>!) -> String? {
if let ab = abEmailAddress {
return Unmanaged.fromOpaque(abEmailAddress.toOpaque()).takeUnretainedValue() as CFStringRef
}
return nil
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
22598 次 |
| 最近记录: |