How to manipulate iOS contacts with SwiftAddressBook? - ios

I'm trying to get all the users contacts and see if they are already singed up in the backend. I'm trying first to get all the contacts using SwiftAddressBook and then I want to edit all the phone numbers and add country code to phone number.
I made this function but it doesn't work, it's only showing phone numbers.
SwiftAddressBook.requestAccessWithCompletion({ (success, error) -> Void in
if success {
if let people = swiftAddressBook?.allPeople {
for person in people {
var phonenumber = String (person.phoneNumbers?.map({$0.value}))
print(phonenumber.characters.last)
if phonenumber.characters.first == "0" {
phonenumber = phonenumber.stringByReplacingCharactersInRange(phonenumber.startIndex..<phonenumber.startIndex.successor(), withString: "+33")
}
print(phonenumber)
}
}
}
else {
print("Fail")
}
})

Well, in first, you should call swiftAddressBook.save() to save the current state of the address book. In second, you are changing a local string variable, which will not affect the address book state. It appears SwiftAddressBook will only make changes to the contacts if you change phoneNumbers array. This should work:
SwiftAddressBook.requestAccessWithCompletion({ (success, error) -> Void in
if success {
if let people = swiftAddressBook?.allPeople {
for person in people {
if let phoneNumbers = person.phoneNumbers {
var phoneNumbersChanged = false
var newPhoneNumbers = [MultivalueEntry<String>]()
for var phonenumber in phoneNumbers {
if phonenumber.value.characters.first == "0" {
phonenumber.value = phonenumber.value.stringByReplacingCharactersInRange(phonenumber.value.startIndex..<phonenumber.value.startIndex.successor(), withString: "+33")
newPhoneNumbers.append(MultivalueEntry(value: phonenumber.value, label: phonenumber.label, id: phonenumber.id))
phoneNumbersChanged = true
} else {
newPhoneNumbers.append(phonenumber)
}
print(phonenumber.value)
}
if phoneNumbersChanged {
person.phoneNumbers = newPhoneNumbers
}
}
}
swiftAddressBook.save()
}
}
else {
print("Fail")
}
})

Related

Can't pass variable value from firebase firestore to another class SWIFT

So I have this function in class Functions :
struct Prices {
var standardPrice: Int!
}
// FUNC PRICING
class Functions {
private var PricingRef: CollectionReference!
var price = Prices()
func getPrice() -> Prices {
PricingRef = Firestore.firestore().collection("ProductXYZ")
PricingRef.getDocuments { (snapshot, error) in
if let err = error {
debugPrint("Error fetching data \(err)")
}
else {
guard let snap = snapshot else { return }
for document in snap.documents {
let data = document.data()
let std = data["standard"] as! String
self.price.standardPrice = Int(std)!
print(self.price.standardPrice!) // This print the intended result
}
}
}
return price
}
}
Then I want to pass the standardPrice value to this class, called PriceList :
class PriceList: UITableViewController {
var price = Prices()
var newStandardPrice = 0
func Price() {
price = Functions().getPrice()
newStandardPrice = price.standardPrice // always error with value nil
}
I always have that error where newStandardPrice is nil.
but the print(self.price.standardPrice!) shows number of result I want.
So as far as I know, the problem here is because it takes time for the firebase firestore to get the data from database.
How do I get the value of standardPrice after its assigned with the new price from firebase database?
Any help will be appreciated
Thankyou
you need to use completion handler because its async function
func getPrice(completion:#escaping (Prices?,Error?)-> Void) {
PricingRef = Firestore.firestore().collection("ProductXYZ")
PricingRef.getDocuments { (snapshot, error) in
if let err = error {
debugPrint("Error fetching data \(err)")
completion(nil,err)
}
else {
guard let snap = snapshot else { return }
for document in snap.documents {
let data = document.data()
let std = data["standard"] as! String
self.price.standardPrice = Int(std)!
print(self.price.standardPrice!) // This print the intended result
completion(self.price.standardPrice,nil)
}
}
}
}
How to use
Functions().getPrice { (price, error) in
if let err = error {
// do something if you get error
} else if let getPrice = price {
// use price
self.price = getPriice
}

altering a variable outside a closure

I am currently encountering a problem. I have a function with an array which has items needing appending to. The items are appended in a closure inside the function and I can see the items in the array only inside the closure. Since the function has a return I need the appended items to be viewed by the function as a whole and not just the array. What can I do to solve this?
var trueOrFalse: Bool = false
var tempArray:[String] = []
let reference_message = reference(.Append).whereField("delay", isEqualTo: 0)
reference_message.getDocuments { (snapshot, error) in
if error != nil {
print(error!.localizedDescription)
}
guard let snapshot = snapshot else { return }
let documents = snapshot.documents
if documents != nil {
for document in documents {
let messageID = document[kMESSAGEID] as? String
tempArray.append(messageID!)
//print(trueOrFalse)
}
}
if trueOrFalse {
if opened && trueOrFalse {
print("Successful Walloping")
}
} else if !trueOrFalse {
if !opened || !trueOrFalse {
decryptedText = placeholderText
}
}
return JSQMessage(senderId: userId, senderDisplayName: name, date: date, text: decryptedText)

loop in a loop not working

I'm working on an app for school project.
After accessing the user's contacts, I want to loop through and show only the contacts who are also users of the app. *Their username is their mobile number.
below are 3 functions.
the first one getAppUsers() works fine.
the third one getDisplayedUser() does not work. and i wonder why
the second one getUserContacts() works. but it is only there to check which part of my loop isn't working. :/
so apparently my loop in a loop has something wrong which i can't figure out (it didn't even get to the "you're HERE"). please help me out. THANKS!
var appUsers = [String]()
var contactStore = CNContactStore()
var userContacts = [CNContact]()
var displayedContacts = [name: phoneNumber]()
func getAppUsers() {
let appUsersQuery = PFUser.query()
appUsersQuery?.findObjectsInBackground { (objects, error) in
if error != nil {
print("WTF")
} else if let users = objects {
for object in users {
print("FYEAH!")
if let user = object as? PFUser {
self.appUsers.append(user.username!)
print(user.username)
}
}
}
}
}
func getUserContacts() {
for b in userContacts {
let c = (b.phoneNumbers[0].value).stringValue
let d = c.replacingOccurrences(of: "\\D", with: "", options: .regularExpression, range: c.startIndex..<c.endIndex)
print("you got here")
print(d)
}
}
func getDisplayedUser() {
for a in appUsers {
for b in userContacts {
let c = (b.phoneNumbers[0].value).stringValue
let d = c.replacingOccurrences(of: "\\D", with: "", options: .regularExpression, range: c.startIndex..<c.endIndex)
print("you're HERE")
print(d)
if a == d {
print("FOUND IT")
print(b.givenName + " " + b.familyName)
}
}
}
}
The getDisplayedUser should be call after the loop finished in in getAppUsers because it is executing in asynchronous mode. I added the row after finished loop below
func getAppUsers() {
let appUsersQuery = PFUser.query()
appUsersQuery?.findObjectsInBackground { (objects, error) in
if error != nil {
print("WTF")
} else if let users = objects {
for object in users {
print("FYEAH!")
if let user = object as? PFUser {
self.appUsers.append(user.username!)
print(user.username)
}
}
// Call it here please ..
self.getDisplayedUser()
}
}
}

Global Variable not Retaining Content

I have a global variable in my class called contacts initialized as - var contacts: [Name]
towards the top of my class. I am wondering why the array is not retaining the populated values. Where the array gets reset is in the comments in the code below.
func extractFromPhone()->[Name]{
swiftAddressBook?.requestAccessWithCompletion({ (success, error) -> Void in
if success {
if let people : [SwiftAddressBookPerson]? = swiftAddressBook?.allPeople {
for person in people! {
// Get Names
var name: Name = Name();
{
name.nickName = nickname;
}
if let fn = person.firstName
{
name.firstName = fn;
}
if let mn = person.middleName
{
name.middleName = mn;
}
if let ln = person.lastName
{
name.lastName = ln;
}
contacts.append(name);
}
}
}
else {
}
// contacts array properly filled here
})
// contacts array becomes empty here
}

Accessing iOS Address Book with Swift: array count of zero

I am trying to write a simple method to ask a user for access to their address book and then print out the name of each person in the address book. I've seen a number of tutorials explaining how to do this in objective-C, but am having a hard time converting them to swift.
Here's what I've done so far. The below block runs in my viewDidLoad() method and checks to see whether the user has authorized access to the address book or not, if they have not authorized access yet, the first if-statement will ask for access. This section works as expected.
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()
}
Once I know the user has granted access, I run the getContactNames() method which is below. After much back and forth, I was finally able to get this to compile by adding the takeRetainedValue() method in order to convert the array returned by ABAddressBookCopyArrayOfAllPeople from an unmanaged array to a managed array, this then allows me to convert the CFArrayRef to an NSArray.
The issue I'm running into is that the contactList array ends up having a count of 0 and the for loop therefore gets skipped. In my simulator, the address book has 6 or 7 records, so I would expect the array to be of that length. Any ideas?
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)")
}
}
One additional point - if I use the ABAddressBookGetPersonCount method, it returns -1.
var count: CFIndex = ABAddressBookGetPersonCount(addressBook);
println("records in the array \(count)") // returns -1
Based on this link ABAddressBookGetPersonCount returns -1 in iOS, it seems that this function returning -1 could be related to permission not being granted, but I definitely have asked for permission in the code above (and granted it when I run the app in the simulator)
This is now all much simpler. The chief thing to watch out for is that if you create an ABAddressBook without authorization, you get an evil address book - it isn't nil but it isn't good for anything either. Here's how I currently recommend that you set up authorization status and request authorization if necessary:
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
}
}
And here's how to cycle through all persons and print out their names:
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())
}
}
There seems to be a bug either with the compiler or the framework where ABAddressBookRef is declared a typealias of AnyObject, but it needs to be NSObject in order to unwrap it from the Unmanaged<ABAddressBookRef>! returned by ABAddressBookCreateWithOptions. A workaround is to convert it to and from an opaque C pointer. The following code works, but it should probably be doing a lot more error checking (and there is also probably a better way of working around this issue):
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)")
}
}
For those looking for the complete working solution, here is how to print out only the contact names, modifying the above code. Invoke getAddressBookNames() to access the address book, e.g. in the viewDidLoad() method.
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
}
And here is the complete code to access the contact names and emails - this is done using the helper methods defined in some of the other answers.
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
}
If anyone is also trying to get the email addresses of the contacts, I found that I needed to create two additional methods similar to the new one Wes showed.
Here's the updated version of the getContactNames() function:
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)")
var emailArray:ABMultiValueRef = extractABEmailRef(ABRecordCopyValue(contactPerson, kABPersonEmailProperty))!
for (var j = 0; j < ABMultiValueGetCount(emailArray); ++j)
{
var emailAdd = ABMultiValueCopyValueAtIndex(emailArray, j)
var myString = extractABEmailAddress(emailAdd)
println("email: \(myString)")
}
}
}
And here are the two additional functions I created:
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
}
Thanks again to Wes for his help on my initial question which helped me figure the above out.
If you need email additionally to matt's answer:
func getContacts() {
if !self.determineStatus() {
println("not authorized")
}
let people = ABAddressBookCopyArrayOfAllPeople(adbk).takeRetainedValue() as NSArray as [ABRecord]
for person in people {
// Name
let name = ABRecordCopyCompositeName(person).takeRetainedValue()
// Email
let emails: ABMultiValueRef = ABRecordCopyValue(person, kABPersonEmailProperty).takeRetainedValue()
for (var i = 0; i < ABMultiValueGetCount(emails); i++) {
let email: String = ABMultiValueCopyValueAtIndex(emails, i).takeRetainedValue() as String
println("email=\(email)")
}
}
}
This is an old question, but another answer may still be useful: I made an approach to solve the problems with address book in swift here: https://github.com/SocialbitGmbH/SwiftAddressBook
I should mention that there are many wrappers for ABAddressBook out there which can help you avoid issues like the one you asked about entirely. Thus I consider the link an "answer" to the problem (though it is not answering how to fix your code)
To add to the info here, this is my solution pieced together from various places (is there a good Apple site that really describes this, the docs I've found basically provide almost nothing more than what the names of args/members are):
let addrBook = ABAddressBookCreateWithOptions(nil,nil).takeRetainedValue()
let contacts = ABAddressBookCopyArrayOfAllPeople(addrBook).takeRetainedValue() as NSArray as [ABRecordRef]
for contact in contacts {
let fname = ABRecordCopyValue(contact, kABPersonFirstNameProperty).takeRetainedValue() as! NSString
let lname = ABRecordCopyValue(contact, kABPersonLastNameProperty).takeRetainedValue() as! NSString
let name = String(fname) + " " + String(lname)
var image:UIImage? = nil
if ABPersonHasImageData(contact) {
image = UIImage(data: ABPersonCopyImageDataWithFormat(contact, kABPersonImageFormatThumbnail).takeRetainedValue() as NSData)
}
if let emailRefs: ABMultiValueRef = ABRecordCopyValue(contact, kABPersonEmailProperty).takeRetainedValue() {
let nEmailsForContact = ABMultiValueGetCount(emailRefs)
if nEmailsForContact > 0 {
if let emailArray: NSArray = ABMultiValueCopyArrayOfAllValues(emailRefs).takeRetainedValue() as NSArray {
for emailW in emailArray {
let email = String(emailW)
if email.containsString("#") {
let c: EmailContact = EmailContact(n: name, e: email, a: false, i: image)
mEmailContacts.append(c)
}
}
}
}
}
}
Oddly, you have to check to make sure there is an image if you want to access it; and you have to check that there is at least one email for a contact before trying to extract them (why doesn't it just return an empty list instead???).
The 'EmailContact" class is something that I made to capture the results, its not shown but the code snippet does show how to extract the info for the current version of swift/ios.
Also, I note that web site settings seem to come up in the EmailArray for contacts as well as actual emails. For now I just check for an "#" sign to determine if its really an email, but is there a better or 'official' way to do that?
Finally, hopefully this is memory leak safe.
Oh, of course this is done after getting permission, if you are not sure how to do that then this site is good: http://www.raywenderlich.com/63885/address-book-tutorial-in-ios
Other answers provided here were useful, and guided this answer, but had errors and/or were not updated for Swift 3. The following class provides a number of simplifications and safety improvements.
Usage is simply to call AddressBookService.getContactNames
There are good reasons to still need to use the ABAddressBook framework, as CNContact does not provide some key data, including creation and modification dates for instance. The deprecated method warnings are somewhat distracting when working with the code, so this code suppresses the warnings that the ABAddressBook methods were deprecated from iOS 9 onwards, instead providing just a single warning to this effect wherever you call the class below.
//
// AddressBookService.swift
//
import AddressBook
#available(iOS, deprecated: 9.0)
class AddressBookService: NSObject {
class func getContactNames() {
let authorizationStatus = ABAddressBookGetAuthorizationStatus()
switch authorizationStatus {
case .authorized:
retrieveContactNames()
break
case .notDetermined:
print("Requesting Address Book access...")
let addressBook = AddressBookService.addressBook
ABAddressBookRequestAccessWithCompletion(addressBook, {success, error in
if success {
print("Address book access granted")
retrieveContactNames()
}
else {
print("Unable to obtain Address Book access.")
}
})
break
case .restricted, .denied:
print("Address book access denied")
break
}
}
private class func retrieveContactNames() {
let addressBook = ABAddressBookCreate().takeRetainedValue()
let contactList = ABAddressBookCopyArrayOfAllPeople(addressBook).takeRetainedValue() as NSArray as [ABRecord]
for (index, record) in contactList.enumerated() {
if let contactName = ABRecordCopyCompositeName(record)?.takeRetainedValue() as String? {
print("Contact \(index): \(contactName))")
}
}
}
}
Not the best solution but until I find this work
let records = ABAddressBookCopyArrayOfAllPeople(self.addressBook).takeRetainedValue()
as NSArray as [ABRecord]
sleep(2)
println(records.count);

Resources