70
AddressBook to Contacts クラスメソッド株式会社 モバイルアプリサービス部 田中 孝明

AddressBook to Contacts

Embed Size (px)

Citation preview

Page 1: AddressBook to Contacts

AddressBook to Contacts

クラスメソッド株式会社 モバイルアプリサービス部

田中 孝明

Page 2: AddressBook to Contacts

自己紹介

名前 田中 孝明

出身 岡山県

iOS 開発歴 2011 ~ (ブランクあり)

入社歴 14

Page 3: AddressBook to Contacts

9月27日に福岡から来ました

Page 4: AddressBook to Contacts
Page 5: AddressBook to Contacts

閑話休題

Page 6: AddressBook to Contacts

AddressBook

Contacts

Page 7: AddressBook to Contacts

Reference• What's New in iOS 9.0

• Introducing the Contacts Framework for iOS and OS X

• Address Book Framework Reference for iOS

• Contacts Framework Reference

• http://qiita.com/koogawa/items/44ce2e1fb127b884d835

Page 8: AddressBook to Contacts

Agenda

• 1. 連絡先について

• 2. AddressBookとContactsについて

• 3. Privacyについて

• 4. Fetchの違いについて

• 5. 連絡先の編集の違いについて

Page 9: AddressBook to Contacts

1. 連絡先について

Page 10: AddressBook to Contacts

連絡先について• 連絡先に登録されているユーザーのデータベースを管理

Page 11: AddressBook to Contacts

連絡先について• 名前

• 電話番号

• email

• 所属

• 住所

• 誕生日

• …etc

Page 12: AddressBook to Contacts

連絡先にアクセスするアプリ

• ユーザーの検索

• 友人の招待

• ユーザーの登録

Page 13: AddressBook to Contacts

活躍の場の例

• サポートデスクの連絡先を追加する

• 社員の連絡先を追加する

• 指定された連絡先のみを削除する

Page 14: AddressBook to Contacts

2. AddressBookとContactsについて

Page 15: AddressBook to Contacts

AddressBookとContactsについて

• どちらにもUIとsuffixが付いているフレームワークがあり、連絡先の追加、参照、削除をする画面を提供している

Page 16: AddressBook to Contacts

• CNContactPickerViewControllerを生成し、presentViewControllerをするだけで簡単に使用できる

ContactsUI

let contactPickerViewController = CNContactPickerViewController() contactPickerViewController.delegate = self self.presentViewController( contactPickerViewController, animated: true, completion: nil)

Page 17: AddressBook to Contacts

• 一覧表示

Page 18: AddressBook to Contacts

• グループ

Page 19: AddressBook to Contacts

•詳細表示

Page 20: AddressBook to Contacts

•複数選択

Page 21: AddressBook to Contacts

地味…

Page 22: AddressBook to Contacts

What's New in iOS 9.0• AddressBookフレームワークがiOS 9からdeprecatedに

• AddressBookUIの方もdeprecatedに

• 現時点ではiOS 9でも使えないこともない…

Page 23: AddressBook to Contacts

What's New in iOS 9.0

• iOS 9でContactsフレームワークが追加された

• iOS 9からしか使用できない

• iOS 8以下もサポートする場合はAddressBookと共存させなければならない

Page 24: AddressBook to Contacts

AddressBookでは⚪⚪だったものが Contactsではxxになる、

といった観点で説明いたします。

Page 25: AddressBook to Contacts

AddressBook

• iOS専用の連絡先アクセスAPI

• Mac用は別に存在する

• Objective-C / Swift両方使用可能

• You must ensure that an instance of ABAddressBookRef is used by only one thread.

Page 26: AddressBook to Contacts

AddressBook

• CoreFoundation…

Page 27: AddressBook to Contacts
Page 28: AddressBook to Contacts

メモリリーク怖い…

Page 29: AddressBook to Contacts

Contacts

• iOS / Macの連絡先アクセスAPI

• watchOS 2に対応

• Objective-C / Swift両方使用可能

• thread-safe(fetch & save)

Page 30: AddressBook to Contacts

Contacts

Page 31: AddressBook to Contacts

3. Privacyについて

Page 32: AddressBook to Contacts

Privacy

Page 33: AddressBook to Contacts

連絡先アクセス許可状態を取得

let status = CNContactStore.authorizationStatusForEntityType(.Contacts)

ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();

• AddressBook

• Contacts

Page 34: AddressBook to Contacts

AddressBook Contacts ステータス

CNAuthorizationStatusNotDetermined NotDetermined 許可/不許可問い合わ

せ前

CNAuthorizationStatusRestricted Restricted

管理者より機能制限 (ユーザー、アプリによる変更は不可)

CNAuthorizationStatusDenied Denied ユーザーによって不許

CNAuthorizationStatusAuthorized Authorized ユーザーによって許可

されている

Page 35: AddressBook to Contacts

AddressBook• 連絡先アクセスの許可をユーザーに問い合わせる

CFErrorRef cfError = NULL; ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &cfError); ABAddressBookRequestAccessWithCompletion( addressBook, ^(bool inGranted, CFErrorRef inCfError) { NSLog(@"inGranted: %d", inGranted); });

Page 36: AddressBook to Contacts

Contacts

• 連絡先アクセスの許可をユーザーに問い合わせる

let store = CNContactStore() store.requestAccessForEntityType( .Contacts, completionHandler:{ (granted: Bool, error: NSError?) -> Void in print("granted: \(granted)") })

Page 37: AddressBook to Contacts

確認用のアラート

Page 38: AddressBook to Contacts

• 許可は設定>プライバシー>連絡先で変更可能

Page 39: AddressBook to Contacts

4. Fetchの違いについて

Page 40: AddressBook to Contacts

AddressBook• RecordIDを指定して取得

• 名前から検索(ABAddressBookCopyPeopleWithName)

Contacts• CNContact.identifierを指定して取得

• 名前から検索(unifiedContactsMatchingPredicate)

Page 41: AddressBook to Contacts

連絡先データベースの作成

Contacts

AddressBookCFErrorRef cfError = NULL; ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &cfError);

let store = CNContactStore()

Page 42: AddressBook to Contacts

AddressBook• RecordIDを指定して取得

• RecordIDはAddressBookデータベースに書き込まれた一意の値

• 型はint 32

int32_t recordId = (int32_t)recordIdNumber.intValue; ABRecordRef person = ABAddressBookGetPersonWithRecordID( addressBook, recordId);

Page 43: AddressBook to Contacts

Contacts• CNContact.identifierを使用して取得

• String型

• AddressBookのRecordIDと互換性がない

let identifier = "035218FA-1E6E-4D1C-9708-76FBC0E55F28"

let contact = try store.unifiedContactWithIdentifier( identifier, keysToFetch:[ CNContactGivenNameKey, CNContactFamilyNameKey])

Page 44: AddressBook to Contacts

AddressBook• 名前から検索

• 「姓」「姓読み」「名」「名読み」のどれか該当するものをFetchする

• 戻り値はCFArrayRef…

NSString *name = @"Appleseed";

CFArrayRef contacts = ABAddressBookCopyPeopleWithName( addressBook, (__bridge CFStringRef)name);

Page 45: AddressBook to Contacts

Contacts• 名前から検索(unifiedContactsMatchingPredicate)

• keysToFetchにはFetchしてきたいプロパティのキーを指定

let predicate = CNContact.predicateForContactsMatchingName( “Appleseed") let contacts = try store.unifiedContactsMatchingPredicate( predicate, keysToFetch:[CNContactGivenNameKey, CNContactFamilyNameKey])

Page 46: AddressBook to Contacts

Contacts• keysToFetchに指定していないプロパティへはアクセスできない

let predicate = CNContact.predicateForContactsMatchingName( "Appleseed") let contacts = try store.unifiedContactsMatchingPredicate( predicate, keysToFetch:[CNContactGivenNameKey, CNContactFamilyNameKey]) let contact = contacts.first print("\(contact!.identifier) \(contact!.givenName) \(contact!.familyName) \(contact!.phoneNumbers)")

Page 47: AddressBook to Contacts

Contacts

• アクセスする前にキーが指定されているかをチェックする

if contact!.isKeyAvailable( CNContactPhoneNumbersKey) {

Page 48: AddressBook to Contacts

Contacts• フルネームを取得する際KeysToFetchに全て指定しない

let contacts = try store.unifiedContactsMatchingPredicate( predicate, keysToFetch:[ CNContactGivenNameKey, CNContactFamilyNameKey, CNContactNamePrefixKey, CNContactMiddleNameKey, CNContactNameSuffixKey, CNContactPhoneNumbersKey])

Page 49: AddressBook to Contacts

Contacts

• CNContactFommatterを使用する

let contacts = try store.unifiedContactsMatchingPredicate( predicate, keysToFetch[ CNContactFormatter. descriptorForRequiredKeysForStyle(.FullName), CNContactPhoneNumbersKey])

Page 50: AddressBook to Contacts

比較

AddressBook Contacts

データベース ABAddressBookRef CNContactStore

連絡先 ABRecordRef CNContact

グループ ABRecordRef CNGroup

Page 51: AddressBook to Contacts

各プロパティ対応AddressBook Contacts

FirstName(Takaaki) kABPersonFirstNameProperty givenName

LastName(Tanaka) kABPersonLastNameProperty familyName

MiddleName(F) kABPersonMiddle NameProperty middleName

Prefix(Mr.) kABPersonPrefix Property namePrefix

Suffix(Jr.) kABPersonSuffix Property nameSuffix

Nickname kABPersonNicknameProperty nickname

Page 52: AddressBook to Contacts

• Conctacs.frameworkからはFetchしてくる必要があるプロパティはキーを指定しなければならない

• AddressBookでIDから検索するロジックを実装している場合はマイグレーション処理等でContact.identifierに置き換える必要がある

Page 53: AddressBook to Contacts

5. 連絡先の編集の違い

Page 54: AddressBook to Contacts

AddressBook• 新規追加の場合(全体)

CFErrorRef cfError = NULL; ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &cfError); if (!addressBook) { NSError *error = (__bridge_transfer NSError *)cfError; NSLog(@"%s: %@", __PRETTY_FUNCTION__, error); } ABRecordRef person = ABPersonCreate();

ABRecordSetValue(person, kABPersonFirstNameProperty, (__bridge CFTypeRef)@"John", &cfError); ABRecordSetValue(person, kABPersonLastNameProperty, (__bridge CFTypeRef)@"Appleseed", &cfError); ABAddressBookAddRecord(addressBook, person, &cfError);

ABAddressBookSave(addressBook, &cfError);

Page 55: AddressBook to Contacts

AddressBook

• ABAddressBookRefを作成する

CFErrorRef cfError = NULL; ABAddressBookRef addressBook = ABAddressBookCreateWithOptions( NULL, &cfError); if (!addressBook) { NSError *error = (__bridge_transfer NSError *)cfError; NSLog(@"%s: %@", __PRETTY_FUNCTION__, error); }

Page 56: AddressBook to Contacts

AddressBook

• ABRecordRefを取得する

ABRecordRef person = ABPersonCreate();

ABRecordSetValue(person, kABPersonFirstNameProperty, (__bridge CFTypeRef)@"John", &cfError); ABRecordSetValue(person, kABPersonLastNameProperty, (__bridge CFTypeRef)@"Appleseed", &cfError);

• 必要なプロパティをセットする

Page 57: AddressBook to Contacts

AddressBook• MultiValueを追加する場合

CFErrorRef cfError = NULL; ABMultiValueIdentifier identifier; ABMultiValueRef multiTel = ABMultiValueCreateMutable(kABMultiStringPropertyType);

CFStringRef label1 = kABPersonPhoneMainLabel; NSString *value1 = @"012-345-6789"; ABMultiValueAddValueAndLabel( multiTel, (__bridge CFTypeRef)(value1), label1, &identifier); CFStringRef label2 = kABPersonPhoneIPhoneLabel; NSString *value2 = @"111-222-3333"; ABMultiValueAddValueAndLabel( multiTel, (__bridge CFTypeRef)(value2), label2, &identifier); ABRecordSetValue( person, kABPersonPhoneProperty, multiTel, &cfError); CFRelease(multiTel);

Page 58: AddressBook to Contacts

AddressBook

• AddressBookに対する操作を指定する

• AddressBookに対するセーブを実施する

ABAddressBookAddRecord( addressBook, person, &cfError);

ABAddressBookSave(addressBook, &cfError);

Page 59: AddressBook to Contacts

Contacts

• 新規追加の場合(全体)

let store = CNContactStore()

let contact = CNMutableContact() contact.givenName = "John" contact.familyName = "Appleseed"

let saveRequest = CNSaveRequest() saveRequest.addContact(contact, toContainerWithIdentifier:nil) do { try store.executeSaveRequest(saveRequest) } catch { abort() }

Page 60: AddressBook to Contacts

Contacts• CNContactStoreを取得

• CNMutableContactを取得する

let store = CNContactStore()

let contact = CNMutableContact()

Page 61: AddressBook to Contacts

Contacts

• 必要なプロパティをセットする

contact.givenName = "John" contact.familyName = "Appleseed"

Page 62: AddressBook to Contacts

Contacts• MultiValueを追加する場合

let mainNumber = CNLabeledValue( label:CNLabelPhoneNumberMain, value:"012-345-6789")

let iPhoneNumber = CNLabeledValue( label:CNLabelPhoneNumberiPhone, value:"111-222-3333") contact.phoneNumbers = [mainNumber, iPhoneNumber]

Page 63: AddressBook to Contacts

Contacts

• CNSaveRequestへデータベースへの操作を指定する

• CNContactStoreに対してセーブを実施する

let saveRequest = CNSaveRequest() saveRequest.addContact( contact, toContainerWithIdentifier:nil)

try store.executeSaveRequest(saveRequest)

Page 64: AddressBook to Contacts

Contacts Changed Notifications

• CNContactStoreDidChangeNotification

• CNContactStoreに変更があった際にNSNotificationCenterから通知を受ける

Page 65: AddressBook to Contacts

まとめ

• 新規作成、編集、削除ロジック部分はあまり変更はない

• Fetchのしかたに変更はあるが、大幅な変更はない

• RecordIDとIdentifierに互換性がない

• Contacts.frameworkはiOS 9以降でしか使用できない

• AddressBookを使用している場合はContactsでも同じロジックで実装し、iOS 8のサポート切れのタイミングで切り離せるようにするほうが良い

Page 66: AddressBook to Contacts

if #available(iOS 9.0, *) {

Page 67: AddressBook to Contacts
Page 68: AddressBook to Contacts
Page 69: AddressBook to Contacts
Page 70: AddressBook to Contacts

ありがとうございました