[watchOS 3] WKSnapshotRefreshBackgroundTask を使用して watchOS アプリの UI 更新する

2016.10.28

はじめに

こんにちは。モバイルアプリサービス部の平屋です。

前回の記事「WKApplicationRefreshBackgroundTask を使用して watchOS アプリをバックグラウンドで更新する」に引き続き、watchOS 3.0 で追加されたバックグラウンド実行用のクラスについての情報を紹介していきます。

本記事では WKSnapshotRefreshBackgroundTask の使用方法を紹介します。

検証環境

  • Xcode Version 8.1
  • iPhone 7, iOS 10.1
  • Apple Watch, watchOS 3.1

watchOS 3 の新機能「Dock」

本記事で紹介する WKSnapshotRefreshBackgroundTask は watchOS 3 の新機能「Dock」に関連します。

Dock は Apple Watch の「サイドボタン」をタップするとアクセスできる機能です。見た目は iOS の「App switcher」のようですが、表示されるのは 「Dock に登録したアプリ」と「最近使用したアプリ 1 つ」です。左右にスワイプしてタップすると、アプリを切り替えることができます。

watchos3-bg-refresh-2-1

WKSnapshotRefreshBackgroundTask

WKSnapshotRefreshBackgroundTask は、Dock 上に表示されるアプリ画面のスナップショットを更新するためのクラスです。

バックグラウンドでこのタスクが実行された際に UI を更新を行い、タスクが完了したことを OS に伝えると、スナップショットが更新されます。

WKSnapshotRefreshBackgroundTask のインスタンス作成は WKApplicationRefreshBackgroundTask と同様に OS 側が行います。

タスクを追加

WKExtensionscheduleSnapshotRefresh(withPreferredDate:userInfo:scheduledCompletion:) メソッドを使用して、スクリーンショット更新用のバックグラウンドタスクをスケジューリングします。

このメソッドの引数は、WKApplicationRefreshBackgroundTask をスケジューリングする際に使用するメソッドと同様です。

func scheduleSnapshot() {
    // fire in 30 seconds
    let fireDate = Date(timeIntervalSinceNow: 30.0)

    WKExtension.shared().scheduleSnapshotRefresh(withPreferredDate: fireDate,
                                                 userInfo: nil,
                                                 scheduledCompletion: { (error) in
                                                    if (error == nil) {
                                                        print("success!")
                                                    }
    })
}

タスクの実行をハンドリング

WKApplicationRefreshBackgroundTask の場合と同様に、バックグラウンドタスクの実行が始まるとシステムはアプリをバックグラウンドで起動させ、WKSnapshotRefreshBackgroundTask を作成します。そして、この作成された WKSnapshotRefreshBackgroundTaskWKExtensionDelegatehandle(_ backgroundTasks: Set) メソッドで取得することができます。

UI を更新する処理を行い、処理が完了したら WKSnapshotRefreshBackgroundTasksetTaskCompleted(restoredDefaultState:estimatedSnapshotExpiration:userInfo:) メソッドを呼びます。

func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) {
    for task : WKRefreshBackgroundTask in backgroundTasks {
        // ...

        if let task = task as? WKSnapshotRefreshBackgroundTask {
            // UI を更新する処理
            self.updateDateLabel()

            // タスクを完了にする
            task.setTaskCompleted(restoredDefaultState: true, // トップ画面に戻すかどうか
                                  estimatedSnapshotExpiration: Date.distantFuture, // スクショを expire させたい日時 
                                  userInfo: nil) // カスタムデータ
        }

        // ...
    }
}

動作結果

ログ

バックグラウンドタスクが 30 秒後に実行されるように指定してみたところ、2分後ぐらいに実行されました。

2016-10-28 04:27:24 +0000 scheduleSnapshot() 93 fireDate: 13:27:54 GMT+9
2016-10-28 04:27:24 +0000 scheduleSnapshot() 99 successfully scheduled snapshot.  All background work completed.
2016-10-28 04:29:37 +0000 handle 55 received background task: <WKSnapshotRefreshBackgroundTask: 0x1456a4e0>
2016-10-28 04:29:37 +0000 updateDateLabel() 108 dateString:13:29:37 GMT+9

スクリーンショット

サンプルアプリ起動時

以下の画像はサンプルアプリを起動した直後のスクリーンショットです。画面上部のラベルはテキスト未設定の状態です。

watchos3-bg-refresh-2-2

この状態で Dock を表示すると、同様の画面が表示されます。

watchos3-bg-refresh-2-3

UI 更新後

以下の画像は、バックグラウンドで UI を更新するタスク (ラベルに日付文字列を設定するタスク) が実行された後に Dock を表示した時のスクリーンショットです。ラベルに日付文字列が設定されたスナップショットが表示されました。

watchos3-bg-refresh-2-4

アプリを起動すると、同様の画面が表示されました。

watchos3-bg-refresh-2-5

さいごに

本記事では watchOS 3.0 で追加された新クラス WKSnapshotRefreshBackgroundTask の使用方法を紹介しました。

次の記事では WKWatchConnectivityRefreshBackgroundTask の使用方法を紹介する予定です。

参考資料