I am attempting to get a list of contacts with a certain name using swift. I have the following code:
let owner = owners[indexPath.row];
var addressBook = ABAddressBookCreateWithOptions(nil, nil)
var addressBookRef: ABAddressBookRef = Unmanaged<NSObject>.fromOpaque(addressBook.toOpaque()).takeUnretainedValue()
let ownerName: NSString = owner["name"]! as NSString
let allContacts = ABAddressBookCopyPeopleWithName(addressBookRef, ownerName)
println("All Contacts: \(allContacts)")
Apparently, allContacts
has a value of Swift.Unmanaged
. I would expect allContacts
to be an NSArray
.
In the tutorial I'm following allContacts
is bridged to NSArray
by adding (__bridge NSArray*)
to ABAddressBookCopyPeopleWithName(addressBookRef, ownerName)
.
What could be causing the issue?
You're doing a lot more wrapping/unwrapping Unmanaged
and Opaque
types than necessary. Your line:
var addressBookRef: ABAddressBookRef = Unmanaged<NSObject>.fromOpaque(addressBook.toOpaque()).takeUnretainedValue()
is equivalent to:
var addressBookRef = addressBook.takeUnretainedValue()
(And besides, you should be using let
unless you want to assign another value to that variable, which seems unlikely. The optimizer will thank you.)
You shouldn't need to cast to Foundation types when passing parameters to AddressBook APIs, either... but I can't make ABAddressBookCopyPeopleWithName
return a non-empty array in my testing, even with ObjC, so it's hard to say.
If you just want to print the array, you need nothing more than this (using ABAddressBookCopyArrayOfAllPeople
instead because of the above issue, but usage of the returned array is the same):
let addressBook: ABAddressBook =
ABAddressBookCreateWithOptions(nil, nil).takeRetainedValue()
let allContacts =
ABAddressBookCopyArrayOfAllPeople(addressBook).takeRetainedValue()
println("All Contacts: \(allContacts)")
(Presumably sometime between getting the addressBook
and using it you're either checking ABAddressBookGetAuthorizationStatus()
or calling ABAddressBookRequestAccessWithCompletion
, right?)
If you want to work with the ABRecord
values in the array, you'll need to do a bit of casting. CoreFoundation types bridged to Foundation types, and Foundation arrays are bridged to Swift arrays, but it doesn't bridge all the way from CF to Swift automagically.
for contact in ((allContacts as NSArray) as [ABRecord]) {
let name = ABRecordCopyCompositeName(contact).takeRetainedValue()
println(name)
}
(I put parentheses in that for
statement to show the hierarchy of operations, but you don't actually need them in your code.)