[SwiftUI]iPhone iOS HealthKitヘルスデータをHealthKitと同期するiPhoneアプリを作る

スポンサーリンク
[SwiftUI]iPhone iOS HealthKitヘルスデータをHealthKitと同期する SwiftUI
スポンサーリンク

体の状態を管理して、健康になるためのiPhoneアプリ制作をできるようになるための方法

iPhone iOSアプリ制作で、XcodeのSwiftUI言語でHealthKitを使った健康アプリ、ウォーキングアプリ、マラソンアプリなどを開発する為に、ヘルスデータを活用する方法を紹介します。

HealthKit は、iPhone や Apple Watch などの複数の HealthKit 対応デバイス間で、または外部サーバーを使用してケア チーム間でデータを共有するかどうかに関係なく、どこでも健康データをスマートに管理するためのツールを提供します。このセッションでは、HealthKit の組み込みの同期識別子メタデータを使用したデータ バージョンの管理、HKAnchoredObjectQuery を使用してヘルス データの変更を検出する方法、および常にどこでも適切なデータを操作できるようにするためのベスト プラクティスについて説明します。

Synchronize health data with HealthKit

Synchronize health data with HealthKit - WWDC20 - Videos - Apple Developer
HealthKit provides you the tools to smartly manage health data anywhere, whether across multiple HealthKit-enabled devices such as iPhone...

こんにちは、WWDC へようこそ。

皆さん、こんにちは。「ヘルス データを HealthKit と同期する」へようこそ。私の名前は Netraです。HealthKit チームのソフトウェア開発者です。ユーザーは、最もプライベートで個人的な情報を健康データの形でデバイスに保存します。Apple プラットフォームでは、HealthKit がこのデータへの簡単なアクセスを提供する基盤です。

また、HealthKit は、アプリで作成したすべてのリッチ エクスペリエンスを有効にします。その結果、私たちは皆、この大きな健康エコシステムの一部になっています。この健康エコシステムの目標は、ユーザーに力を与えることです。ユーザーは、このエコシステムのどこからでも自分の健康データにアクセスできます。Apple Watch から、Apple がリリースしたアプリから、すべてのすばらしいアプリから。

そのため、健康データに加えた変更によってユーザーを驚かせたくありません。私たちは皆、この健康エコシステムの善良な市民になりたいと思っていますが、それは非常に困難になる可能性があります. この講演では、HealthKit がまさにそれを実現するお手伝いをします。ですから、私たちの目標はユーザーに力を与えることであることを思い出してください。ユーザーは常にデータを管理する必要があり、健康データへの変更は常にユーザーの意図を反映する必要があります。

今日は、2 つの重要なトピックについて説明します。まず、HealthKit での変更の監視について説明します。

私たちは、健康エコシステムのどの部分からでもデータを読み書きできることを知っています。この健康データを使用して、複数の種類のアプリやデータの視覚化を強化できます。アプリは、HealthKit の変更に適切に対応できるようになっている必要があります。

次に、HealthKit と同期して外部データ ストアを維持する方法について詳しく説明し、HealthKit がこれを非常に簡単にする方法を説明します。

最初のトピックである HealthKit の変更の監視から始めます。これらの概念を処理するアプリを作成しましょう。これは、怪我から回復している患者のためのアプリです。このアプリでは、患者が毎日の歩数を追跡できます。時間が経つにつれて、毎日の歩数の進捗状況を監視したいと考えています。さらに、私たちの患者は週に数回理学療法士を訪ね、特定の歩行テストを完了します. テストは6分間の歩行距離テストです。患者が平らな面を 6 分間歩いたときに移動した距離を測定します。理学療法士は、このテストの結果を自分のマシンに入力しますデータは週次レポートとしてユーザーの iPhone に同期されます。

このような重要なデータを監視する最良の方法の 1 つは、グラフを使用することです。患者は、実際の値をあまり気にしなくても、歩数の上昇傾向または下降傾向を簡単に確認できます。ここに、患者と理学療法士にとって非常に興味深いグラフがあります。過去 1 週間の毎日の患者の合計歩数を追跡します。Apple Watch と iPhone の両方から歩数を記録できるようになりました。1 日の正確な歩数を取得したいと考えています。このようなグラフを作成するときに最初に行うことは、HKStatisticsCollectionQuery に到達することです。これは、ほとんどのグラフを作成するときに到達する必要がある最初のクエリです。このクエリについては、前回の講演「HealthKit の使用を開始する」で既に学習しているかもしれません。そうでない場合、そしてそれが初めての場合は、最初にその講演を見に行きたいと思うかもしれません. 実際、その講演で作成した SmoothWalker アプリを使用してアプリを作成します。

作成したばかりのグラフをリモート サーバーに送信して、ユーザーの進行状況に関心のある理学療法士もグラフを読み取れるようにする必要があります。これはどのように見えるでしょうか?まず、最初の週のグラフをサーバーに送信します。

次に、その週のデータに変更があった場合、たとえば、より多くの歩数が収集された場合、その週の新しいデータをサーバーに送信する必要があります。ここでは、外部データをリモート サーバーと見なしますが、デバイス上でローカルに維持される外部データベースである可能性もあります。Core Data または SQLite データベースを使用している可能性があります。

これで、HKStatisticsCollectionQuery を使用してデータをロードできることがわかりました。新しいデータを取得するには、定期的にクエリを実行する必要があります。これは、アプリの起動時と、その後数時間ごとに発生する可能性があります。

しかし、新しい変化に反応するためにそれを使用することには、いくつかの欠点があります。

データが頻繁に変更されない場合、HKStatisticsCollectionQuery を複数回実行することになり、計算が冗長になります。

また、すべてのデータを毎回送信します。これは、ネットワーク リソースの浪費になります。

HealthKit には、このようなユースケース専用の別のツールがあります。これは HKAnchoredObjectQuery と呼ばれます。HKAnchoredObjectQueryを使用すると、ヘルス データベースの更新を監視できます。

これは、正常性データベースの変更のスナップショットを提供します。このスナップショットには、新しいサンプルと削除されたサンプルの両方が含まれています。このクエリがどのように機能するか見てみましょう。

名前が示すように、アンカー オブジェクト クエリにはアンカーが必要です。

アンカーは、健康データベースの進化における特定の時点を表します。この時点以降、ヘルス データが追加または削除された可能性があります。

このアンカーを使用すると、このクエリから最後に受け取ったすべてのサンプルを特定できます。

このアンカーを HealthKit に提供すると、HealthKit はその時点以降の変更のみを返します。

さて、最初のクエリでは、アンカーは nil になります。

現時点で、HealthKit にはサンプル A、B、および C があります。

クエリを実行すると、HealthKit は、指定したデータ型に基づいてすべてのデータを返します。この場合、updateHandler でサンプル A、B、および C を受け取ります。

アンカーが更新され、HealthKit は updateHandler で新しいアンカーを提供します。

これは、 HealthKit が updateHandler でサンプルを返す最後の時点です。

updateHandler が最後に呼び出されてから、さらにサンプルが追加されたとします。これらには、サンプル D と E が含まれます。さらに、サンプル B はその後削除されました。以降のすべてのクエリの実行では、前のアンカー以降の変更のみがupdateHandler に返されます。これらには、サンプル D と E、サンプル B の削除が含まれますが、A と C については含まれません。

HKAnchoredObjectQueryまたは HealthKit の任意のクエリを使用する場合、扱うデータの種類とユース ケースについて少し考える必要があります。ステップの場合、実際のサンプル自体はあまり気にしません。実はApple Watchは今から5年前に発売されました。これらのデバイスによって大量のデータが生成されます。それは同期するための大量のデータです。すべてのサンプルではなく、累積統計が必要です。

個々のサンプルを気にする場合は他にもあります。これらは、あまり頻繁に生成されないサンプルである可能性があります。各データ型は異なる方法で処理できます。データをどのようにクエリして同期するかについて、少し時間をかけて考える必要があります。達成しようとしているタスクは、必要なクエリのタイプを駆動します。

最小限のデータのクエリには、パフォーマンス上の利点もあります。現在のユースケースでは、理学療法士が統計グラフを利用できるようにしたいだけです。どうやってこれを行うのですか?HKAnchoredObjectQuery からのサンプルをいつでも実行して、グラフを計算できます。しかし、2 つのクエリを連携させてみませんか? アンカー オブジェクト クエリを使用すると、述語とサンプル タイプをまさに探しているものに設定できます。アンカー オブジェクト クエリによって HealthKit の変更が更新されると、返されたサンプルの日付を確認し、それを使用して統計収集クエリを作成および実行できます。

それらの日に返された統計は、更新されたグラフ データとしてリモート コンピューターに送信できます。

これで、新しいデータをサーバーに送信するだけです。

これも、ローカル Core Data モデルまたはリモート サーバーの NSURLSession である可能性があります。これをよりよく理解するために、これがコードでどのように見えるかを見てみましょう。

まず、アンカー オブジェクト クエリのパラメーターを設定します。サンプルの種類は歩数です。

PersistedAnchor を使用してアンカー パラメータを設定します。アンカーを永続化すると、最後のクエリ以降の HealthKit の変更のみを取得できます。

initialResultsHandlerと updateHandler には同じ動作が必要なので、handler 変数に同じブロックを設定します。

ハンドラーで、HealthKit から返されたサンプルをアンラップします。

サンプルから述語を作成します。これは、サンプルが取得された日付である可能性があります。これは、統計収集クエリを初期化するために使用する述語です。

ここでは、PersistedAnchor も更新する必要があります。

このブロックの最後で、述語を使用して HKStatisticsCollectionQuery を作成する fetchStatistics メソッドを呼び出すことができます。

設定したパラメーターでHKAnchoredObjectQuery を初期化します。これらには、サンプル タイプ、nil 述語、アンカー、そして最後に resultsHandler と updateHandler が含まれます。

最後に、healthStore でクエリを実行します。

fetchStatistics メソッドが HKStatisticsCollectionQuery を作成する方法を見てみましょう。もう一度、パラメータを設定します。統計収集クエリを日単位でバケット化する必要があります。これを実現するために、アンカー日を月曜日の午前 0 時に設定し、間隔パラメーターを 1 日に設定します。サンプルの種類は再び歩数になります。

次に、これらのパラメーターを使用して HKStatisticsCollectionQueryを初期化できます。各日の合計歩数が必要なため、オプションはcumulativeSumになります。

ご覧のとおり、アンカー オブジェクト クエリで作成された述語がここに用意されています。

initialResultsHandler では、statisticsCollection をアンラップし、このデータをリモート サーバーに送信します。

いつものように、healthStore でクエリを実行した後にのみ更新を取得します。

HealthKit から外部サーバーにデータを送信する方法を見てきました。次に、外部ストアからデータを受信し、HealthKit にも保存する次のステップに進む必要があります。

前に見たように、患者は週に数回理学療法士のオフィスを訪れ、6 分間の歩行テストを完了します。

6 分間歩行テストは、平らな面を 6 分間歩いたときに個人が移動できる距離です。多くの場合、理学療法士が患者の運動能力を測定するために使用します。

今年、HealthKit に新しい一連のモビリティ タイプが導入されました。データ型の 1 つは、6 分間の歩行テスト距離です。これらは、アプリの目的に完全に適合します。理学療法士から受け取ったテスト データを6 分間の歩行テスト距離サンプルとして保存できます。私たちのアプリでは、理学療法士がこれらの 6 分間の歩行テストの値を記録し、週次レポートが患者のデバイスに同期されます。週間レポートには、曜日ごとの 6 分間の歩行テスト距離のグラフが含まれています。

また、グラフの下に表示されているグラフの個々のサンプルもあります。これは、理学療法士または患者が個々のテスト結果をより深く掘り下げたい場合に使用します。これにより、各データ型を異なる方法で処理する必要があるという考えに戻ります。扱うデータの種類と、ユースケースについて考える必要があります。sixMinuteWalkTestDistanceは HealthKit に頻繁に書き込まれるわけではなく、患者または理学療法士は個々のテスト サンプルに関心を持つ可能性があります。したがって、前に見たステップとは異なり、このグラフでは各サンプルをプロットする価値があります。以前は、ステップ サンプルをデバイスからリモート サーバーに同期していました。現在、理学療法士のサーバーにこの週次レポートがあります。サーバーから患者のデバイスに同期し、対応するサンプルを HealthKit に保存します。

これにより、患者はアプリで sixMinuteWalkTestDistance グラフを個々のテスト サンプルとともに表示できます。

変更を HealthKit に保存するときは、注意すべき点がいくつかあります。増分サンプルを HealthKit に保存するだけです。すべてのデータを単に削除してから再度保存すると、ユーザーの健康データの状態が一貫しなくなる可能性があります。新しいサンプルには、ユーザーに関する新しい健康データが反映されています。たとえば、新しい 6 分間の歩行テストや新しい手順がカバーされています。たぶん、ユーザーが記録した体重の変化さえも。

サンプルを削除するときは、それが実際にアプリによって以前に作成されたサンプルであることを確認する必要があります。自分で明示的に保存していないデータを削除することはできません。

ここでのベスト プラクティスは、最初にサンプルをクエリしてから削除することです。

サンプルの追加または削除は、常にユーザーの意図を反映する必要があります。ユーザーがサンプルを削除するつもりがなかった場合は、おそらく削除すべきではありません。

ここで、いくつかの課題が発生します。理学療法士が特定のテストを更新したい場合はどうしますか? たとえば、6 月 18 日のテストでは、患者は 6 分間の歩行テストで 400 メートルをカバーしました。このデータは、後でエラーを反映するために理学療法士によって更新されました。

実際の走行距離は450メートル。これは少し難しいかもしれません。サンプルを編集するときは、実際に新しいサンプルを削除して追加する必要があります。そうしないと、重複したサンプルが保存される可能性があります。これは、サンプルを照会し、理学療法士が編集したサンプルと正確に一致させてから、新しいサンプルを保存する必要があることを意味します。

他のサンプルを編集する必要がない場合は、変更中にそれらのサンプルの複製を保存していないことを確認する必要があります。

健康データは、iPhone や Apple Watch など、患者のすべてのデバイスで利用できます。サンプルの変更は、すべてのデバイスで正しく反映される必要があります。あるデバイスにサンプルを保存した場合は、そのサンプルを別のデバイスに再度保存していないことを確認する必要があります。

この間ずっと、ユーザーの意図を正しく反映していることを確認する必要があります。これは非常に複雑に見えるかもしれませんが、HealthKit を使用すると、これを非常に簡単に行うことができます。

HealthKit には、HKMetadataSyncIdentifier および HKMetadataSyncVersion と呼ばれる 2 つのメタデータ キーが含まれています。同期識別子は文字列で、バージョンは数字です。

この識別子により、健康エコシステムのどこにいても、ユーザーのデバイスを問わずサンプルを認識することができます。バージョンは、サンプルがいつ更新されたかを理解するのに役立ちます。

サンプルに同期識別子を設定すると、HealthKit はサンプルの重複コピーがユーザーのヘルス データベースに保存されないようにします。

同期識別子とバージョンの組み合わせにより、HealthKit はバージョン番号が増加した場合にのみサンプルを更新できます。

さらに、同期識別子を使用して行われるすべての操作は、トランザクションに対して安全です。つまり、エラーが発生した場合でも、データが一貫した状態にあるという安心感を得ることができます。健康データは、ユーザーのすべてのデバイスで利用できます。同期識別子を使用すると、サンプルをデバイス間で一貫した状態に維持できます。

リモート サーバーには、識別子とバージョン 1 を持つサンプルがあります。

アプリは、リモート サーバーから患者の iPhone にサンプルを同期します。

これが最初のサンプルであることを考慮すると、HealthKit は正常に保存します。

HealthKit は、新しいサンプルが保存されたことを認識すると、これを患者のすべてのデバイスに同期します。患者が Apple Watch を持っていれば、Apple Watch に同期します。

リモート サーバーも Watch 上のアプリにデータを同期していて、サンプルを再度保存しようとすると、HealthKit はサンプルが既に存在することを認識し、それを無視します。

ここで、理学療法士が6 分間の歩行テストで完了した距離を更新することを決定した場合、同期識別子の一貫性を保ちながらバージョン番号を増やしてサンプルを更新します。

このサンプルが患者のデバイスに同期されると、HealthKit はバージョン番号が増加したことを認識します。

前のサンプルを新しいサンプルで上書きします。

サンプルは再び患者のすべてのデバイスに同期されます。

リモート サーバーがサンプルのバージョン 2 を Apple Watch に同期すると、HealthKit はサンプルが既に存在することを認識し、サンプルを無視します。

ご覧のとおり、HealthKit は保存と同期中にすべての競合解決を管理します。バージョン管理と同期という困難なタスクは、一貫した識別子を維持するだけに軽減されました。前に患者の週次報告を見ましたが、実際にこのデータをモデル化するにはどうすればよいでしょうか? これを行う 1 つの方法は、週次レポートをレポート クラスとして表すことです。このレポート クラスは、高レベルの同期識別子で識別できます。

レポート クラスには、その週の 6 つの MinuteWalkTestDistance サンプルすべてのリストが含まれます。

各サンプルには、高レベルのレポート ID から派生した同期 ID メタデータ キーを含めることができます。

このようにして、各サンプルを異なる週で一意に参照できます。

データは、このレポート クラス モデルの形式でリモート サーバーから患者のデバイスに同期でき、このリストの個々の HK サンプルを HealthKit に保存できます。

これをデモで見てみましょう。このアプリ、SmoothWalker は、前回の講演「HealthKit 入門」で既に作成しています。このプロジェクトは、開発者の Web サイトからサンプル コードとしてダウンロードすることもできます。アプリでこの週次レポート ビュー コントローラーを作成します。Fetch ボタンを押すと、6 分間の歩行サンプルがサーバーから取得され、ビュー コントローラーに入力されます。WeeklyReportTableViewController クラスを見てみましょう。Fetch ボタンを選択すると、 didTapFetchButton メソッドが呼び出されます。

ここでは、ネットワークからサーバーの応答を取得します。

次に、serverResponse で handleServerResponse メソッドを呼び出します。handleServerResponse メソッドを実装しましょう。

ここでは、serverResponse から週次レポートを取得し、対応するサンプルを HealthKit に保存します。

最初に行うことは、serverResponse から週次レポートを取得することです。

この後、週次レポートのすべてのサンプルをループします。ここでわかるように、週次レポートのサンプルをループして、それぞれの HKQuantitySample を返しています。

このループでは、最初に HKQuantitySample のパラメーターを設定します。

単位メーターを持つ数量があり、値は serverHealthSample から取得されます。sampleType は sixMinuteWalkTestDistance です。最後に、開始日と終了日があります。

次に、これらのパラメーターを使用して HKQuantitySample を初期化します。

サンプルの種類、数量、開始日と終了日があり、今のところメタデータは「nil」です。ループから返されたサンプルは、HealthKit に保存する必要があります。

それでは、サンプルを HealthKit に保存します。

ご覧のとおり、これらのサンプルはすべて healthStore を使用して保存されており、完了ハンドラーが新しいデータを HealthKitからビュー コントローラーに読み込みます。このコードを実行して、どのように見えるか見てみましょう。

[Fetch] ボタンを選択すると、View Controller に週次レポートのサンプルが読み込まれます。

ただし、もう一度 Fetch ボタンを選択すると、複製されたサンプルが HealthKit に保存されていることがわかります。これは正しくありません。HealthKit に重複したデータは必要ありません。HKQuantitySampleにメタデータを含めると、これがどのように変化するかを見てみましょう。メタデータ ディクショナリを作成し、パラメータのリストに追加します。serverHealthSample から同期識別子を取得し、それをキーの HKMetadataKeySyncIdentifier に追加します。同様に、serverHealthSample から syncVersionを取得し、それをキーの HKMetadataKeySyncVersion に追加します。次に、このメタデータ ディクショナリをHKQuantitySample のパラメーター リストに追加します。このコードをもう一度実行して、どのようになるか見てみましょう。

このデモのために、アプリの起動時に HealthKit の 6 分間の歩行サンプルをすべて削除するコードを追加しました。ただし、サンプルを削除するときは常に注意し、ユーザーの意図が反映されていることを確認してください。

これで、Fetch を選択すると、6 分間の歩行サンプルが週次レポートに表示されます。ただし、Fetch を複数回選択しても、重複するサンプルはありません。ご覧のとおり、HKMetadataSyncIdentifierとHKMetadataSyncVersion を使用してサンプルを保存すると、HealthKit に重複したサンプルがなくなります。このグラフを裏付けるデータをモデル化しました。外部データを HealthKit と同期することは、見た目ほど難しいことではありません。HealthKit は、健康エコシステムの変化を効率的に監視し、複数のデバイス間でデータを一貫して維持できるツールを提供します。いくつかのベストプラクティスをご紹介しましょう健康データの同期に取り組んでいる場合。ユーザーのデータを変更するときは、常にユーザーの意図を反映していることを確認してください。ユーザーは、自分の健康データの変更に驚いたり驚いたりしないでください。

効率的なクエリを実行する方法を考えてください。クエリを組み合わせて、最小限のデータをフェッチして同期することを検討できるかもしれません。

最後に、健康データは複数のデバイスにまたがって存在するため、同期識別子とバージョン番号を使用して、デバイス間でデータの一貫性を保ちます。

Apple プラットフォームの健康エコシステムのほんの一部に触れただけですが、ここでできることはまだまだたくさんあります。健康データを扱うときは、自分がやろうとしていることのセキュリティとプライバシーへの影響について考えてください。これは、外部データ ストアで健康データを管理している場合に特に重要です。Apple には、これに役立つリソースがたくさんあります。

今日お見せした美しいグラフ ビジュアライゼーションを作成したい場合は、CareKit フレームワークをご覧ください。CareKit は、健康管理とケアの提供に特化したアプリを開発するためのオープンソース フレームワークです。最後に、HealthKit には、豊富なヘルス エクスペリエンスを作成するために使用できる他の複数の機能があります。これらは、ワークアウト、臨床健康記録、高頻度のデータ タイプにまで及びます。これらのすべての HealthKit リソースを使用して作成された素晴らしいアプリを見るのをとても楽しみにしています。ご覧いただきありがとうございます。素晴らしい WWDC をお楽しみください。

コメント