Skip to content

Instantly share code, notes, and snippets.

@prrane
Created September 4, 2014 05:34
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save prrane/f2c0dde7158a02eed878 to your computer and use it in GitHub Desktop.
Save prrane/f2c0dde7158a02eed878 to your computer and use it in GitHub Desktop.
Swift: Get contact emails from AddressBook
// based on : http://stackoverflow.com/questions/24752627/accessing-ios-address-book-with-swift-array-count-of-zero
// http://stackoverflow.com/questions/24752627/accessing-ios-address-book-with-swift-array-count-of-zero
class func extractABAddressBookRef(abRef: Unmanaged<ABAddressBookRef>!) -> ABAddressBookRef? {
if let ab = abRef {
return Unmanaged<NSObject>.fromOpaque(ab.toOpaque()).takeUnretainedValue()
}
return nil
}
class func testAddressBook() {
if (ABAddressBookGetAuthorizationStatus() == ABAuthorizationStatus.NotDetermined) {
println("requesting access...")
var errorRef: Unmanaged<CFError>? = nil
addressBook = extractABAddressBookRef(ABAddressBookCreateWithOptions(nil, &errorRef))
ABAddressBookRequestAccessWithCompletion(addressBook, { success, error in
if success {
// prrane: add a call back some time later
// ABAddressBookRegisterExternalChangeCallback(addressBook, callback: (addressBook:ABAddressBookRef, info:CFDictionaryRef) -> , <#context: UnsafeMutablePointer<()>#>)
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()
}
}
class 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 {
if record != nil {
var contactPerson: ABRecordRef = record
println ("\n\n")
let emailProperty: ABMultiValueRef = ABRecordCopyValue(record, kABPersonEmailProperty).takeRetainedValue() as ABMultiValueRef
let allEmailIDs: NSArray = ABMultiValueCopyArrayOfAllValues(emailProperty).takeUnretainedValue() as NSArray
for email in allEmailIDs {
let emailID = email as String
println ("contactEmail : \(emailID) :=>")
}
if let contactNickname = ABRecordCopyValue(contactPerson, kABPersonNicknameProperty).takeRetainedValue() as? NSString {
println ("\t\t contactNickname : \(contactNickname)")
}
if let contactFirstName = ABRecordCopyValue(contactPerson, kABPersonFirstNameProperty).takeRetainedValue() as? NSString {
println ("\t\t contactFirstName : \(contactFirstName)")
}
if let contactLastName = ABRecordCopyValue(contactPerson, kABPersonLastNameProperty).takeRetainedValue() as? NSString {
println ("\t\t contactLastName : \(contactLastName)")
}
}
}
}
@armstrongnate
Copy link

This is very helpful! I found that if the contact does not list an email you will get a crash on what is currently line 50.

let allEmailIDs: NSArray = ABMultiValueCopyArrayOfAllValues(emailProperty).takeUnretainedValue() as NSArray

So I added a check just before to make sure there are any emails.

if ABMultiValueGetCount(emailProperty) > 0 {
  let allEmailIDs: NSArray = ABMultiValueCopyArrayOfAllValues(emailProperty).takeUnretainedValue() as NSArray
}

Thanks.

@poparotsy
Copy link

Still fails if ABMultiValueRef is nil, user doesn't have emails in the case below.

let emails: ABMultiValueRef = ABRecordCopyValue(person,kABPersonEmailProperty).takeRetainedValue() as ABMultiValueRef

    if ABMultiValueGetCount(emails) > 0 {
        let allEmails = ABMultiValueCopyArrayOfAllValues(emails).takeRetainedValue() as NSArray
        if allEmails.count > 0 {
            for email in allEmails {
                println(email)
            }
        }
    }

@yuanjilee
Copy link

l got a better ways to get emails and share it (in Swift 2.0*)

let emails: [String] = LCKPhoneContact.extractMultivalueProperty(record, propertyName: kABPersonEmailProperty)

class func extractProperty(recordRef: ABRecord, propertyName : ABPropertyID) -> T? {
//the following is two-lines of code for a reason. Do not combine (compiler optimization problems)
let value: AnyObject? = ABRecordCopyValue(recordRef, propertyName)?.takeRetainedValue()
return value as? T
}

class func extractMultivalueProperty(recordRef: ABRecord, propertyName : ABPropertyID) -> Array {
var array = Array()
let multivalue : ABMultiValue? = extractProperty(recordRef, propertyName: propertyName)
for i : Int in 0..<(ABMultiValueGetCount(multivalue)) {
let value : String? = ABMultiValueCopyValueAtIndex(multivalue, i).takeRetainedValue() as? String

  if let value = value {
    array.append(value)
  }
}
if array.count > 0 {
  return array
}
else {
  return []
}

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment