Upload
alexsander-akers
View
2.400
Download
0
Embed Size (px)
DESCRIPTION
AddressBook.framework is definitely no one's favourite framework, especially with its outdated CoreFoundation-based API. This talk aims to show you how you can leverage AddressBook in your Swift apps whilst staying sane in the process.
Citation preview
AddressBook.swi,Alexsander*Akers*,*@a2
Address&Book&“Classes”
ABAddressBookRefAn#address#book.
ABRecordRefA"person,"group,"or"source.
ABMultiValueRefA"mul&'valued"property.
Why$AB_____Ref?
When%AddressBook.framework%debuted%in%Mac%OS%X%10.2%Jaguar,%it%featured%both%CBbased%Core%FoundaDon%and%ObjecDveBC%APIs.%However,%when%the%iPhone%SDK%became%public%with%the%release%of%iPhone%OS%2.0,%its%AddressBook.framework%only%featured%the%CBbased%Core%FoundaDon%API.
tl;drC"based(Core(Founda.on(APIs(aren't(difficult(to(use,(per(se,(but(Swi<(makes(it(a(bit(harder.
ABAddressBookRefAn#address#book.
ABAddressBookRef+Crea.on
Objec&ve(C
extern ABAddressBookRef ABAddressBookCreateWithOptions( CFDictionaryRef options, CFErrorRef *error);
Swi$
func ABAddressBookCreateWithOptions( options: CFDictionaryRef!, error: UnsafeMutablePointer<Unmanaged<CFErrorRef>?>) -> Unmanaged<ABAddressBook>!
ABAddressBookRef+Crea.onvar error: Unmanaged<CFErrorRef>? = nil
var addressBook: ABAddressBookRef? =ABAddressBookCreateWithOptions(nil, &error)?.takeRetainedValue()
if let addressBook = addressBook { // Success!} else { // Error let e = error!.takeUnretainedValue() as AnyObject as NSError println("An error occurred: \(e)")}
ABAddressBookRef+Authoriza2onlet addressBook: ABAddressBookRef = /* ... */
ABAddressBookRequestAccessWithCompletion(addressBook) { (success, error) in if success { // We can use the address book. } else { // User denied the request. let e = error as AnyObject as NSError println("An error occurred: \(e)") }}
ABRecordRefA"person,"group,"or"source.
ABRecordRef
Person
ABRecordRef
Group
ABRecordRef
Source
ABRecordRef*Acquisi/onlet peoplePickerDelegate = /* some object */
let peoplePicker = ABPeoplePickerNavigationController()peoplePicker.delegate = peoplePickerDelegate
viewController.presentViewController( peoplePicker, animated: true, completion: nil)
ABRecordRef*Acquisi/on// In your ABPeoplePickerNavigationControllerDelegate
func peoplePickerNavigationController( peoplePicker: ABPeoplePickerNavigationController!, didSelectPerson person: ABRecord!) {
// Do something with person}
func peoplePickerNavigationControllerDidCancel( peoplePicker: ABPeoplePickerNavigationController!) {
let p = peoplePicker.presentingViewController! p.dismissViewControllerAnimated(true, completion: nil)}
ABRecordRef*Acquisi/onlet addressBook: ABAddressBookRef = /* ... */
// You can get a record's ID with ABRecordGetID()let recordID: ABRecordID = /* ... */
let unmanagedPerson: Unmanaged<ABRecordRef>? =ABAddressBookGetPersonWithRecordID(addressBook, recordID)// ABAddressBookGetGroupWithRecordID// ABAddressBookGetSourceWithRecordID
if let person = unmanagedPerson?.takeUnretainedValue() { // You have a person!}
ABRecordRef*Values
func ABRecordCopyValue( record: ABRecord!, property: ABPropertyID) -> Unmanaged<AnyObject>!
let kABPersonFirstNameProperty: ABPropertyIDlet kABPersonMiddleNameProperty: ABPropertyIDlet kABPersonLastNameProperty: ABPropertyID// etc.
ABRecordRef*Valueslet firstName: CFStringRef = ABRecordCopyValue( record, kABPersonFirstNameProperty)?.takeRetainedValue()
if firstName != nil { let fn = firstName! as AnyObject as String println("The first name is \(fn).")}
ABRecordRef*Valueslet phones: ABMultiValueRef? = ABRecordCopyValue( record, kABPersonPhoneProperty)?.takeRetainedValue()
if let phones = phones { // We have an ABMultiValueRef.}
ABMul&ValueRefA"mul&'valued"property.
ABMul&ValueRef
Almost'a'dic,onary?'!
// Duplicate keys are bad.let phones: [String : String] = [ "Home": "+1 (718) 861-4986", "Work": "+1 (212) 340-1938", "iPhone": "+1 (917) 530-9127", "iPhone": "+1 (917) 251-8826"]
Keys%in%a%mul,-value%don't%have%to%be%unique.%A%person%could%have%two%mobile%numbers,%like%the%day%iPhone%/%night%iPhone%guy.
ABMul&ValueRef
An#array#of#tuples.#!
let phones: [(String, String)] = [ ("Home", "+1 (718) 861-4986"), ("Work", "+1 (212) 340-1938"), ("iPhone", "+1 (917) 530-9127"), ("iPhone", "+1 (917) 251-8826")]
This%representa,on%makes%more%sense%because%the%uniqueness%contstraint%is%gone.%The%tuple%consists%of%a%label%and%a%value.
ABMul&ValueReflet count: Int = ABMultiValueGetCount(phones)for i in 0..<count { let label: String = ABMultiValueCopyLabelAtIndex( phones, i )!.takeRetainedValue() as AnyObject as String
let value: String = ABMultiValueCopyValueAtIndex( phones, i )!.takeRetainedValue() as AnyObject as String
println("\(label) -> \(value)")}
ABMul&ValueRef
Debugger'Output
_$!<Home>!$_ -> +1 (718) 861-4986_$!<Work>!$_ -> +1 (212) 340-1938iPhone -> +1 (917) 530-9127iPhone -> +1 (917) 251-8826
_$!<WTF>!$_
_$!<Home>!$_ !!→!!!kABHomeLabel_$!<Work>!$_ !!→!!!kABWorkLabel_$!<Other>!$_!!→!!!kABOtherLabel
These%are%just%some%of%the%constants%used%by%AddressBook.framework%that%are%localized%in%Phone,%Contacts%and%ABPersonViewController%before%display%to%the%user.
AddressBook.swi,Alexsander*Akers*,*@a2