続 CloudKitを使ってみた Swift版 - サブスクリプション編

[前回](http://qiita.com/tfutada/items/83b30311a5fbc3fad212)の続きです。

iCloudではクラウド上のデータの変更(追加/更新/削除)を、プッシュ通知(APN)で受け取ることができます。
プッシュ通知はシミュレータでは動作しないので、実機をつないで実行します。

基本的には[アップルデベロッパーライブラリ](https://developer.apple.com/library/ios/documentation/DataManagement/Conceptual/CloudKitQuickStart/SubscribingtoRecordChanges/SubscribingtoRecordChanges.html)の説明の通りです。(Swiftに読み替えて)

プッシュ通知を受けとるには、`CKSubscription`と`CKNotificationInfo`を使用します。

```swift:CloudTableViewController.swift
    func saveSubscription() {
        
        let collection = CKContainer.defaultContainer().publicCloudDatabase
        
        // 1. Create a subscription on Persons.
        let subscription = CKSubscription(recordType: "Persons", predicate: NSPredicate(format: "TRUEPREDICATE"), options: [CKSubscriptionOptions.FiresOnRecordCreation, CKSubscriptionOptions.FiresOnRecordUpdate])

        // 2. Set a Notification details on it.
        let notificationInfo = CKNotificationInfo()
        notificationInfo.alertLocalizationKey = "Person record has changed!"
        notificationInfo.shouldBadge = true
        
        subscription.notificationInfo = notificationInfo // set it to the subscription
        
        // 3. Save the subscription on 'Persons' record.
        collection.saveSubscription(subscription) { (subscription:CKSubscription?, error:NSError?) in

            if let error = error {
                print("error occurred: \(error)")
            }
            
            print("Subscription is saved. \(subscription?.subscriptionID)")
        }
    }
```

1. レコードタイプ`Persons`にレコードを追加`FiresOnRecordCreation`, 更新`FiresOnRecordUpdate`した場合にイベントを受け取るように定義します。
2. プッシュ通知のメッセージを設定します。`CKNotificationInfo.alertLocalizationKey`
3. 作成したサブスクリプション定義を、iCloudサーバに登録します。`saveSubscription(subscription: CKSubscription,`


プッシュ通知を有効にするため`AppDelegate.swift`の`application:didFinishLaunchingWithOptions:`に下記を追加します。

```swift:AppDelegate.swift
import CloudKit
...
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        let notificationSettings = UIUserNotificationSettings(forTypes: [.Alert, .Sound], categories: nil)
        application.registerUserNotificationSettings(notificationSettings)
        application.registerForRemoteNotifications()
        print("registered!")
        return true
    }
```

```swift:AppDelegate.swift
    func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
        let notification = CKNotification(fromRemoteNotificationDictionary: userInfo as! [String:NSObject])
        print("An alert has been recieved from iCloud: \(notification.alertBody)")
    }
```

`notification.alertBody`にメッセージの内容が渡されます。

以上です。
実機をつなぎ、ビルド&実行します。

プッシュ通知許可のダイアログが出ます。OKします。

<img width="375" alt="IMG_0583.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/75231/f734e07f-ba32-dad9-20a4-4a7b4a96d955.jpeg">


CloudKitダッシュボードを開きます。
`Subscriptoin Types`メニューを開き、サブスクリプションが登録されたのを確認します。


![CloudKit_Dashboard.jpg](https://qiita-image-store.s3.amazonaws.com/0/75231/44dd4d77-dd58-63f0-fceb-045ffc83c11a.jpeg)


今回は、手動でレコードを新規作成してみます。(本来は、別のデバイスから登録することになります。)
`PUBLIC DATA > Default Zone`を開きます。`+`をクリックし、レコードの情報を入力します。
`Save`をクリックします。(非常にわかりづらいですが、画面の右下にあります。)

![CloudKit_Dashboard.jpg](https://qiita-image-store.s3.amazonaws.com/0/75231/9b6e3cae-27ce-e098-685f-af0edfac8be3.jpeg)


すぐに、実機にプッシュ通知が送られます。

<img width="375" alt="IMG_0584.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/75231/812ad54e-d786-1a44-34c7-f2963b31f897.jpeg">


## 参考
https://www.hackingwithswift.com/read/33/overview