iOS 9から追加されたContacts Frameworkを使って連絡先アプリのデータを取得してみる

# これは何

iOS 9 で `Address Book UI frameworks` が **deprecated** になりました。

参考：[iOS 9 / watchOS 2 で deprecated になる or 引退していくAPIたち - Qiita](http://qiita.com/koogawa/items/3e36acd758de81b9a85a#address-book-ui-frameworks)

上記の記事にも書いたように、今後は `Contacts frameworks` および `Contacts UI frameworks` を使うことが推奨されます。

この記事では、Contacts frameworks を使って iPhone の連絡先アプリからアドレスデータを取得する方法を簡単に解説します。


![スクリーンショット 2015-09-27 22.29.27.png](https://qiita-image-store.s3.amazonaws.com/0/8292/88b87664-b973-44ad-6f75-a8f86242dd97.png "スクリーンショット 2015-09-27 22.29.27.png")
▲連絡先アプリ

# 準備

まずは必要なフレームワークを追加してimportします。

![スクリーンショット 2015-09-27 22.32.03.png](https://qiita-image-store.s3.amazonaws.com/0/8292/bec58135-4fa1-6c3b-51f3-00f0ed0ccb57.png "スクリーンショット 2015-09-27 22.32.03.png")

```swift
import Contacts
import ContactsUI
```

後に説明する `CNContactPickerDelegate` プロトコルにも準拠しておきましょう。

```swift
class ViewController: UIViewController, CNContactPickerDelegate {
```

# 実装

## CNContactPickerViewControllerを表示

連絡先を選択するための `CNContactPickerViewController ` を表示します。

```swift
let picker = CNContactPickerViewController()
picker.delegate = self

// Show the picker
self.presentViewController(picker, animated: true, completion: nil)
``` 

このコードを実行すると、初回時に次のダイアログが出現し、連絡先へのアクセス許可が求められます。

![Simulator Screen Shot 2015.09.27 20.38.15.png](https://qiita-image-store.s3.amazonaws.com/0/8292/cf0e94b0-a99b-e908-01d2-390830b2327a.png "Simulator Screen Shot 2015.09.27 20.38.15.png")

ここで許可すると、iPhoneに登録されている連絡先リストが表示されます。

![Simulator Screen Shot 2015.09.27 21.52.26.png](https://qiita-image-store.s3.amazonaws.com/0/8292/e0bbc3c8-36c4-0b94-ab9a-aaec7afbf68d.png "Simulator Screen Shot 2015.09.27 21.52.26.png")

この中から適当な人物を選んでタップすると、次の画面（以下<b>アドレス詳細画面</b>と勝手に呼ぶことにします）が表示されます。

![Simulator Screen Shot 2015.09.27 22.49.48.png](https://qiita-image-store.s3.amazonaws.com/0/8292/4ce75a12-8460-38c4-b46f-5ac867a4c2ae.png "Simulator Screen Shot 2015.09.27 22.49.48.png")

上記の数行を実装するだけで、これだけのUIを用意してくれます。

また、アドレス詳細画面に表示する項目は次のように制限できます。

```swift
// 電話番号、メールアドレス、住所のみ表示する
let displayedItems = [CNContactPhoneNumbersKey, CNContactEmailAddressesKey, CNContactPostalAddressesKey]
picker.displayedPropertyKeys = displayedItems
```

指定できるキーについては

[Metadata Keys - CNContact Class Reference](https://developer.apple.com/library/prerelease/ios/documentation/Contacts/Reference/CNContact_Class/index.html#//apple_ref/doc/constant_group/Metadata_Keys)

を参照してください。

## 項目タップ時の処理

アドレス詳細画面の各項目（ **プロパティ** と呼びますが、クラスの"プロパティ"と名前が被ってややこしいので、本記事では普通に「項目」と呼ぶことにします）をタップすると次のメソッドが呼ばれます。

```swift
func contactPicker(picker: CNContactPickerViewController, didSelectContactProperty contactProperty: CNContactProperty) 
```

選択された項目は `CNContactProperty ` クラスとして取得できます。

`CNContactProperty ` クラスは次のプロパティを持っています。（一部のみ解説）

* contact: `CNContact` - その人物の名前、住所、電話番号など様々な情報
* key: `String` - どの項目が選択されたのか（例：Phone）
* value: `AnyObject?` - 選択された項目の内容（例：03-1234-5678）

以下は、選択された人物の名前と、どの項目がタップされたかをアラートに表示するサンプルです。

```swift
func contactPicker(picker: CNContactPickerViewController, didSelectContactProperty contactProperty: CNContactProperty) {
    let contact = contactProperty.contact
    let contactName = CNContactFormatter.stringFromContact(contact, style: .FullName) ?? ""
    let propertyName = CNContact.localizedStringForKey(contactProperty.key)
    let title = "\(contactName)'s \(propertyName)"

    dispatch_async(dispatch_get_main_queue()) {
        let alert = UIAlertController(title: title,
            message: contactProperty.value?.description,
            preferredStyle: .Alert)
        alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
        self.presentViewController(alert, animated: true, completion: nil)
    }
}
```

実行結果：

![Simulator Screen Shot 2015.09.27 22.59.59.png](https://qiita-image-store.s3.amazonaws.com/0/8292/846c0785-9a52-e33f-7831-3f9e35472027.png "Simulator Screen Shot 2015.09.27 22.59.59.png")

## キャンセルボタンタップ時の処理

キャンセルボタンがタップされると次のメソッドが呼ばれます。

```swift
func contactPickerDidCancel(picker: CNContactPickerViewController)
```

キャンセル後に何か処理を行いたい場合はここに記述すると良いでしょう。（ここで CNContactPickerViewController を dismiss する必要はないようです）

# サンプルコード

今回紹介したサンプルコードは以下にアップしてあります。

https://github.com/koogawa/ContactsUISample

# 参考リンク

* [ContactsUI Framework Reference](https://developer.apple.com/library/prerelease/ios/documentation/ContactsUI/Reference/ContactsUI_Framework/index.html#//apple_ref/doc/uid/TP40016207)
* [Introducing the Contacts Framework for iOS and OS X](https://developer.apple.com/videos/wwdc/2015/?id=223) - WWDC 2015 Videos