3

watchOS 3 アプリを作成しようとしていますが、バックグラウンド タスクでコンプリケーションを更新したいと考えています。

まず、 内のバックグラウンド タスクでサーバーから新しいデータを取得しますhandle()。その後、 を呼び出してアクティブな合併症を更新しcomplicationServer.reloadTimeline(for:)ます。

コンソールに「UPDATE COMPLICATION」というメッセージが表示されるので、コードが実行されます。

しかし、リロード後も、コンプリケーションはまだ古いデータを表示します。ウォッチフェイスを切り替えて元に戻すと、コンプリケーションがリロードされることがあります。バックグラウンド タスクからコンプリケーションをリロードするために何か他のことをする必要がありますか?

func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) {
    for task : WKRefreshBackgroundTask in backgroundTasks {
        if (WKExtension.shared().applicationState == .background) {
            if task is WKApplicationRefreshBackgroundTask {
                let dataProvider = DataProvider()
                dataProvider.getData(station: "Name", completion: { (data, error) in
                    self.updateComplication()
                    self.scheduleNextBackgroundRefresh()

                    task.setTaskCompleted()
                })
            }
        } else {
            task.setTaskCompleted()
        }
    }
}

func updateComplication() {
    let complicationServer = CLKComplicationServer.sharedInstance()

    for complication in complicationServer.activeComplications! {
        print("UPDATE COMPLICATION")
        complicationServer.reloadTimeline(for: complication)
    }
}
4

1 に答える 1

5

現在のアプローチ:

そこでは、watchOS 2 と watchOS 3 のアプローチが混在しています。

  • WKApplicationRefreshBackgroundTask (watchOS 3 の新しいアプローチ)
    1. DataProvider は非同期転送を開始します (バックグラウンドではなくフォアグラウンドにあると想定する古い watchOS 2 アプローチ)。
      • そのバックグラウンド スレッド (一時停止されているかどうかにかかわらず、まだ完了していないバックグラウンド タスクの) は、非同期転送が完了すると、バックグラウンド タスクがその完了を処理することを期待します。

つまり、バックグラウンド更新タスクがバックグラウンドで非同期転送を待機することを期待していました。これは少し複雑です (更新タスクは他の作業が完了するのを待つのではなく、バックグラウンドで作業を行うことになっているため)。

watchOS 3 のより良い方法:

非同期転送は一時停止できるため、URLSessionバックグラウンド転送を使用した方がよいでしょう。

常に URLSession バックグラウンド転送を使用してデータをアップロードおよびダウンロードします。バックグラウンド転送は別のプロセスで発生します。アプリが終了した後もデータを転送し続けます。一方、非同期のアップロードとダウンロードはアプリで中断されます。watchOS アプリの実行時間は短いため、アプリが中断される前に非同期転送が完了することを保証することはできません。

WKURLSessionRefreshBackgroundTaskをバックグラウンド転送に応答させることで、セッションの完了後に拡張機能をバックグラウンドで起動し、そのセッションのデータをデータ プロバイダーに渡してから、コンプリケーションを更新できます。

データ プロバイダーに関する提案:

データの転送とデータの提供の両方の責任があるようです。ネットワーク部分を別のコンポーネントに分割し、単純にデータのリポジトリにすることを検討することもできます。

ある種のシングルトン(舞台裏)であることを意図しているという印象を受けますが、インスタンスを として初期化しますDataProvider()

読みやすさの観点からすると、提供されたコードからは、追加データ ソースがデータを受信したデータ プロバイダーと同じデータ プロバイダーを使用することは明らかではありません。

オプションの強制アンラップは避ける必要があります。

が nil の場合activeComplications(前回の更新と今回の更新の間にウォッチ フェイスからコンプリケーションが削除された場合など)、コードは無愛想にクラッシュします。

guardまたはを使用しif letて、まだアクティブな合併症があることを最初に確認する必要があります。

于 2016-06-29T13:44:11.170 に答える