24
AddressBook.swi, Alexsander Akers , @a2

AddressBook.swift

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

Page 1: AddressBook.swift

AddressBook.swi,Alexsander*Akers*,*@a2

Page 2: AddressBook.swift

Address&Book&“Classes”

ABAddressBookRefAn#address#book.

ABRecordRefA"person,"group,"or"source.

ABMultiValueRefA"mul&'valued"property.

Page 3: AddressBook.swift

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.

Page 4: AddressBook.swift

ABAddressBookRefAn#address#book.

Page 5: AddressBook.swift

ABAddressBookRef+Crea.on

Objec&ve(C

extern ABAddressBookRef ABAddressBookCreateWithOptions( CFDictionaryRef options, CFErrorRef *error);

Swi$

func ABAddressBookCreateWithOptions( options: CFDictionaryRef!, error: UnsafeMutablePointer<Unmanaged<CFErrorRef>?>) -> Unmanaged<ABAddressBook>!

Page 6: AddressBook.swift

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)")}

Page 7: AddressBook.swift

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)") }}

Page 8: AddressBook.swift

ABRecordRefA"person,"group,"or"source.

Page 9: AddressBook.swift

ABRecordRef

Person

Page 10: AddressBook.swift

ABRecordRef

Group

Page 11: AddressBook.swift

ABRecordRef

Source

Page 12: AddressBook.swift

ABRecordRef*Acquisi/onlet peoplePickerDelegate = /* some object */

let peoplePicker = ABPeoplePickerNavigationController()peoplePicker.delegate = peoplePickerDelegate

viewController.presentViewController( peoplePicker, animated: true, completion: nil)

Page 13: AddressBook.swift

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)}

Page 14: AddressBook.swift

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!}

Page 15: AddressBook.swift

ABRecordRef*Values

func ABRecordCopyValue( record: ABRecord!, property: ABPropertyID) -> Unmanaged<AnyObject>!

let kABPersonFirstNameProperty: ABPropertyIDlet kABPersonMiddleNameProperty: ABPropertyIDlet kABPersonLastNameProperty: ABPropertyID// etc.

Page 16: AddressBook.swift

ABRecordRef*Valueslet firstName: CFStringRef = ABRecordCopyValue( record, kABPersonFirstNameProperty)?.takeRetainedValue()

if firstName != nil { let fn = firstName! as AnyObject as String println("The first name is \(fn).")}

Page 17: AddressBook.swift

ABRecordRef*Valueslet phones: ABMultiValueRef? = ABRecordCopyValue( record, kABPersonPhoneProperty)?.takeRetainedValue()

if let phones = phones { // We have an ABMultiValueRef.}

Page 18: AddressBook.swift

ABMul&ValueRefA"mul&'valued"property.

Page 19: AddressBook.swift

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.

Page 20: AddressBook.swift

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.

Page 21: AddressBook.swift

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)")}

Page 22: AddressBook.swift

ABMul&ValueRef

Debugger'Output

_$!<Home>!$_ -> +1 (718) 861-4986_$!<Work>!$_ -> +1 (212) 340-1938iPhone -> +1 (917) 530-9127iPhone -> +1 (917) 251-8826

Page 23: AddressBook.swift

_$!<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.

Page 24: AddressBook.swift

AddressBook.swi,Alexsander*Akers*,*@a2