ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
効率的なawait:SwiftUIのバックグラウンドタスク
Background Tasksにより、Appではシステムのイベントに応答したり、時間的制約のあるデータを最新の状態に保ったりすることができるようになります。SwiftUI Background Tasks APIを使用して、タスクを簡単に処理する方法をご覧ください。パフォーマンスや電力を維持しながら、Swift Concurrencyを使用してネットワーク応答やバックグラウンド更新などを処理する方法を紹介します。
リソース
関連ビデオ
WWDC22
WWDC21
-
ダウンロード
♪ ヒップトップ調のゆるやかな音楽 ♪ ♪音楽が流れる 「効率的なawait: SwiftUIのバックグラウンドタスク」 watchOS Frameworks teamの 技術者John Gallagherです この講演ではSwift Concurrencyを使用して すべての Appleプラットフォームで一貫して バックグランドタスクの処理の為の SwiftUI APIについて学びます まずは嵐の日の空を撮影する App「Stormy」という サンプルAppを紹介します このAppはバックグランドタスクを 使って嵐の日の空の写真を撮るAppです 次にAppがどのように バックグランドタスクを使っているか そしてどのように作動するかを説明します 次にSwiftUI の新しいAPI を使用してこれらの タスクを処理する方法を学びます 最後にどのようにSwift Concurrencyを使い タスクを容易に処理することを確認します 新しいAPIはMac上で動作するiOS Appを含む watchOS ・iOS・tvOS Mac・Catalyst・Widgetsで 共通です ある環境でバックグランドタスクを 処理することを学んだ概念とパターンを 他の環境で行う作業にも 適用できるのです Swift Concurrencyを利用することで 新しいAPI は深くネストされた完了ハンドラや コールバックの必要性を減らし 副作用が大きいmutable stateも減らしました Swift Concurrency の ネイティブなタスクキャンセルは Appがシステムによってバックグラウンドで 終了させられるのを避けるために タイミングよくタスクを完了させます 頭を使うのが好きな人向けに 空の写真を撮るように促す 「Stormy」というAppを作ります 天気が荒れている日に 空の写真を撮るように促すAppです このAppは嵐の日の正午空の写真を 撮るよう促す通知を表示します 通知をタップすると空の写真が撮影されます プロフィールにアップロードし 後の楽しみとして 見ることができます この写真をバックグランドで アップロードします アップロードが完了すると Appから再度通知が来ます ではバックグランドタスクがどうやって 機能するかを見ましょう この図で高レベルでAppの 通知が嵐の日のみ送信され バックグランドタスクを活用する しくみについて 検証していきます 前景Appの実行時間を左のバーで バックグランドAppの実行時間を中央のバーで システムを右のバーで 表現します Appを初めてフォアグランドで表示したときに 初めてバックグランドAppのタスクを 設定する機会になり タスクを午後に更新することができます ユーザーがAppを終了しAppが中断されると システムは設定した時間に バックグランドでAppを再起動する事を 感知します タスクを正午に設定したので その時間帯にシステムが Appをバックグランドで起動し バックグランドAppの更新タスクを送信します このバックグランドの稼働時間から 外が嵐のような状態かどうか 判断する必要があります そうであればユーザーに 通知を送る必要があります まず始めに現在の天気を確認する為に 天気予報サービスに ネットワーク要求を行います URIセッションがバックグランドに 設定されているため ネットワーク・リクエストの完了を 一時的に待つことができます 気象データのバックグランドネットワークへの 要求が完了すると Appは新しい URLSessionバックグラウンドタスクで 再びバックグラウンドランタイムを 与えられます 気象データ要求の結果を受けて 結果が手元にあれば Appは外が嵐のようかどうか把握し 空の写真を撮るように促す通知を 送ることができます URLセッションのタスクが終わったので システムはAppを再停止することができます 1つのバックグランドタスクの詳細を説明し どのように動作するかを見てみましょう そこで1つのApp更新の バックグランドタスクの概要を 詳しく見ていきます ここで少しズームアップしてみます まずシステムはAppを起動し バックグランドタスクを更新します そしてやはりバックグラウンドから 外が荒れているかどうかを確認するための ネットワークリクエストを行います 理想的にはネットワーク要求が Appの更新に割り当てられた バックグランドの制限内に完了するのが 理想的です ネットワークの応答があったらすぐに通知を 投稿したいです Appの更新時に必要な作業はすべて完了し システムは再びAppを 停止することができます しかしネットワークからの気象データ要求が 間に合わない場合はどうするのでしょうか Appが現在のタスクの バックグランド実行時間が残り少ない場合は システムがAppに 時間が残り少ないことを通知し この状況をしっかりと処理する 機会を与えます Appの完了の合図がない場合 バックグランドの作業が時間切れする前に システムによって終了され 今後のバックグランドタスクの要求が 抑制されるかもしれません この場合ネットワーク要求が バックグランドネットワーク・リクエスト であることを確認しAppの更新タスクを 直ちに完了できるようにします 追加のタスクのために再起動させます Appの更新タスクを即座に完了し バックグランドでの実行時間が追加されます バックグランドURLセッションが 設定されているため システムはAppを再度停止することができます さてSwiftUIのバックグランドタスク APIが どうStormyの構築に役立つか見ていきましょう 始めるのには基本的なAppが必要です 次にバックグランドAppの更新を 明日の正午に設定するよう 関数を設定します まず明日の正午を表す日付を作成します 次にバックグランドAppの更新請求をし 最も早い開始日の明日の正午に作成し スケジューラに送信します これは明日の正午にAppを起動するよう システムに指示するものです この関数はユーザーが最初にAppを開き 毎日正午に嵐を 通知するように要求します シーン修正を使い バックグランドタスクに対応する ハンドル名を 登録できます Appがバックグランドタスクを受信すると この修正プログラムで登録されたブロックが バックグランドタスクと一致します そこで事前に予約可能な appRefreshタスクを使用し バックグランドタスクでの 限定的な実行時間を 提供することができます リクエストとハンドラに 共通の識別子を使用すると 対応するタスクを受け取ったときに どのハンドラを呼び出すかを 識別できるようになります 明日も予定があることを確認するため バックグランドタスクを開始します スケジューラのAppRefreshで バックグランドタスクの実行時間を開始します 関数を呼び出し明日の正午にセットします 正午のバックグランドの 実行時間がくり返され嵐かどうかを チェックするためにネットワーク要求を作成し Swiftのawaitのキーワードを使って 結果を待ちます ネットワークのリクエストが返ってきて 外が荒れていたら空の写真を アップロードするように ユーザーに通知を 送ります クローズの本体が戻るとシステムから Appに割り当てられたバックグランドタスクは 暗黙的に完了とマークされ システムはAppを 再び停止することができます ここではSwift Concurrencyを使うことで 作業が完了したときのために 明示的なコールバックを必要とせずに バックグラウンドタスクで潜在的に長く続く 処理を行うことができました 通知の追加など Appleプラットフォーム全体の多くのAPIは すでに非同期操作のための Swift Concurrencyをサポートしています ここではUserNotificationCenterにある 非同期のaddNotificationメソッドを使って notifyForPhotoの非同期関数を 素直に実装することができました Swift Concurrencyとasync/awaitが 重い仕事をしさらにどのように簡単に バックグランドタスクを処理するかを 見ていきましょう これまで紹介してきた非同期のisStormy関数を 書いてみましょう この非同期関数は外の天気を確認するために ネットワークリクエストを行う必要があります まず始めに共有されたURLSessionを取得し 天気データのリクエストを インスタンス化します URLSessionはSwift Concurrencyを採用し ネットワークからデータを ダウンロードするためのメソッドを持ち 非同期文脈から待ち受けることが可能です ネットワークの応答があれば 天気予報のデータを読み込むことができます しかし実行時間内にAppが ネットワーク要求を完了できない場合は どうでしょう? この場合URLSession を バックグランド用として設定し URL Session が Appの起動イベントを送信することが 確実になされるよう 留意しておいてください コードの話に戻りますが URLSessionを共有していました その代わりにバックグランド設定から URLSessionを作成する必要があります プロパティをtrue に設定します これはAppが休止状態でも ネットワーク要求が実行されるように システムに指示し 要求の完了時にURLが バックグランドタスクとして実行するよう 起動します watchOS上でバックグラウンドで動作する Appが行うネットワークリクエストは すべてバックグラウンドのURLSessionを通じて リクエストする必要があるため これはwatchOS上で 特に重要であることに注意してください まだこれで終わりではありません バックグラウンドタスクの 実行時間が終了するとき システムはバックグラウンドタスクの モディファイアに 提供されたクロージャを実行している 非同期タスクをキャンセルすることを 思い出してください つまりここで行われたネットワーク要求は バックグランドの実行時間が終了した時点で ここで行われたネットワーク要求も終了します キャンセルに対応し処理するため タスクキャンセルハンドラー関数を 使うことが出来ます 結果を直接待つかわりに ダウンロードしたデータを タスクコントローラーの呼び出しにし これを待ちます タスクキャンセルハンドラーに渡される 最初のブロックの非同期プロシージャを 実行し待ち受けます 2つ目のonCancelの末尾のクロージャは タスクがキャンセルされたときに 実行されるコードです ここでランタイムが期限切れで 即時のネットワーク要求が キャンセルされた場合 ネットワーク要求をバックグラウンド ダウンロードタスクに昇格させ その上でレジュームを呼び出すと Appが中断されても持続する バックグラウンドダウンロードが 開始されるようになっています このコードでは 同じ URLSession を使って 両方をバックアップしているため 基盤となるネットワークリクエストを 2 回行うことはなく URLSession はプロセス内のリクエストを すべて重複排除します 最後にAppがバックグラウンドの URLSession からの起動を処理するように セットアップされていることを 確認する必要があります 再度バックグランドタスクモディファイアを 再び使うことも可能ですが 今回はURLセッションを使用します バックグラウンドのURLSessionの設定に 同じ識別子を使用することで このブロックのみが 呼び出されることを 確認します バックグラウンドタスクを処理するための 新たな統一されたSwiftUI APIに取り組みました 並行処理によってタスクの完了と期限切れを 管理することがより簡単になりました Swift の並行処理について詳しくは WWDC2021のトークをご覧ください 「SwiftのAsync/awaitについて」 SwiftUIにおける並行処理については これもWWDC2021で発表された 「SwiftUIでの並行処理」をお勧めします ご視聴ありがとうございました “効率的なawait :SwiftUIのバックグラウンドタスク”
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。