今更だけど『HealthKit』について調べてみた

# はじめに

この記事は、[NTTテクノクロス Advent Calendar 2022](https://qiita.com/advent-calendar/2022/ntt-tx) 12日目です。

NTTテクノクロスの神長(ジンチョウ)です。社内では、モバイル向けアプリ開発の技術支援、技術ガイド・技術記事の執筆、[社内研修講師](https://www.ntt-tx.co.jp/products/soft_dojyo)等を担当してます。

また、業務外では以下活動を行ってます。

- [小学生を対象にしたプログラミング教育(社外ブログ『エンジニアが本気で⼩学⽣向けプログラミング教育をやってみた』を参照してください。)](https://www.ntt-tx.co.jp/column/cross_field.html)
- 社内の仲間と[技術書典へ書籍の出展(最新刊『宣言的UIアプリ開発食べくらべ』)](https://techbookfest.org/product/i26qH6sfdvfucWuyaCYH6q?productVariantID=1TjCkN4JWFr8q2xp4wfGTm)

今回 **[『HealthKit』](https://developer.apple.com/documentation/healthkit)** に関する記事を書いた理由は、以下の通りです。

- 近年の健康志向の高まりを受け、社内でも健康とフィットネスデータを活用したプロダクトがより増えてきたから。
- HealthKitの知識が無かった為、社内勉強会向けに勉強。折角なのでQiitaでも共有できればと考えたから。

今回の記事では、HealthKitに関する以下項目を説明します。HealthKitを利用したプロダクトに関わる方々の基本的な知識のキャッチアップに役立てて頂ければと思ってます。

- **HealthKitとは**
- **HealthKitで扱うデータ**
- **HealthKitデータの利用**
- **ユーザーのプライバシー保護**
- **HealthKitに関連する『App Store Review Guidlines』**
- **HealthKitに関連する『Human Interface Guidelines』**

# 環境

- Xcode Version 14.1 (14B47b)
- iOS Version 16.1.2 **※1**

**※1 事前に[Developer Mode](https://developer.apple.com/documentation/xcode/enabling-developer-mode-on-a-device)をONにしておく必要があります。**

# HealthKitとは

iPhone・AppleWatchを経由して健康データ(心拍数や睡眠に関するデータ等)、フィットネスデータ(ランニングやウォーキング、サイクリング等)の収集と保存 **※2** 、データを使ったソーシャルインタラクションの実現 **※3** を提供するフレームワークです。イメージは、[HealthKit](https://developer.apple.com/documentation/healthkit)のリファレンスより抜粋したものです。

![HealthKitImage.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59827/1ad218ae-fa05-ca5b-f590-154237600e6d.png)


**※2 iPhoneの設定でiCloudへのバックアップを有効にしている場合、収集された健康データとフィットネスデータは自動的にバックアップされます。**

**※3 [HealthKit](https://developer.apple.com/documentation/healthkit)のリファレンスでは、『例えば、友人同士で毎日の歩数を競うチャレンジに参加する場合、各自が好みのハードウェアデバイスとアプリを使って歩数を記録し、グループの全員が同じソーシャルアプリを使ってチャレンジに参加することができます。』といった説明がされています。**

# HealthKitで扱うデータ

HealthKitは、HealthKitストアで様々なデータを扱います。ここでは、カテゴリ毎に説明します。

## HealthKitストア

健康データとフィットネスデータを保存する領域です。iPhoneとAppleWatchはそれぞれ独自のHealthKitストアを持ち、データはiPhoneとAppleWatchの間で自動的に同期されます。容量を節約するために、古いデータはAppleWatchから定期的に削除されます。データの読み書きは、`HKHealthStore`を使用して行います。

なお、AppleWatchで利用可能な最も古いサンプルを判定する場合、`earliestPermittedSampleDate()`を使用します。

## Characteristic data

Characteristic dataは、ユーザーの生年月日、血液型、性別、肌タイプなど、通常変更されないデータを指します。
これらは、`dateOfBirthComponents()`、`bloodType()`、`biologicalSex()`、`fitzpatrickSkinType()`を使用して読み取ることができます。変更・保存は、個人で開発したアプリからはできません。変更・保存する場合は、Apple社が提供するHealthアプリを使用する必要があります。

## Sample data

ユーザーの健康データは、特定の時点のデータを表すSample dataに保存されます。
Sample dataは、`HKSample`のサブクラスであり`HKObject`のサブクラスです。

### HKObject

HKObjectは、HealthKitのすべてのサンプルタイプのスーパークラスです。
HKObjectのサブクラスは、全てイミュータブルであり、次のプロパティを持ちます。

- UUID(エントリに一意の識別子)
- メタデータ
- デバイス(データを生成したハードウェアデバイス)
- ソースリビジョン(オブジェクトがHealthKitストアに保存される時のオブジェクトのソースとバージョン)

### HKSample

HKObjectのサブクラスです。後述するサンプルオブジェクトは、特定の時点のデータを表し、全てのサンプルオブジェクトはHKSampleのサブクラスです。これらのオブジェクトは、次のプロパティを持ちます。

- Type(サンプルの種類。睡眠分析サンプル、身長サンプル、歩数サンプル等)
- Start date(サンプル収集時の開始時間)
- End date(サンプル収集時の終了時間)

### サンプルオブジェクト

サンプルオブジェクトは、4つのサブクラスに分けられます。

- Category samples(`HKCategorySample.`):有限のカテゴリに分類できるデータ(睡眠時間等)
- Quantity samples(`HKQuantitySample.`):数値として保存できるデータ(ユーザーの身長や体重のほか、歩数、体温、脈拍等)
- Correlations(`HKCorrelation`)：1つまたは複数のサンプルを含む複合データ(食べ物と血圧のデータ等)
- Workouts(`HKWorkout`):ワークアウトのデータ(ランニング、サイクリング等)

## Workout data

ユーザーのフィットネスデータ。フィットネスデータは、`HKSample`のサブクラス`HKWorkout`を介して扱います。

## Source data

Sample dataを保存したアプリやデバイスに関する情報(`HKSourceRevision`オブジェクト)やデータを生成したハードウェアデバイスに関する情報(`HKDevice`オブジェクト)です。

## Deleted objects

HealthKitストアから削除されたアイテムのUUIDを一時的に保存するために使用されるオブジェクトです。(`HKDeletedObject`)(Deleted objectsを使用し、ユーザーや他のアプリによってオブジェクトが削除された場合の応答に利用します。)

# HealthKitデータの利用

ここでは、プロジェクトの設定を含めたHealthKitデータ(健康データ、フィットネスデータ)の利用方法をサンプルコードを交えて説明します。

## プロジェクトの設定

以下手順に沿ってプロジェクトの設定を行います。

* GeneralのFrameworks,Libraries,and Embedded ContentにHealthKitとHealthKitUIフレームワークを追加する。

* Signing & CapabilitiesにHealthKitを追加する。アプリがユーザーの臨床記録にアクセスする必要がある場合のみ『Clinical Health Records』を選択。

![SigningCapabilities.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59827/1480410a-b625-889f-fba4-18c97e8c982c.png)

* Custom iOS Target Propertiesに以下のプロパティを追加する。追加時に **必ず12文字以上の説明文を記載する必要があります。** **追加しない場合、アプリがクラッシュするので注意してください。**
    * `Privacy - Health Update Usage Description`・・・データの保存
    * `Privacy - Health Share Usage Description`・・・データの読み出し
    * `Privacy - Health Records Usage Description`・・・アプリが臨床記録の読み取り許可 **※4**

![Properties.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59827/64c573d7-b96b-8f55-6b9a-98dc6de94ed1.png)

**※4 特定の臨床記録データにアクセスする必要がある場合に設定する必要があるキー。臨床記録の読み取りに際しては、ユーザーのプライバシーを保護から3つ以上の必須臨床記録タイプを指定する必要があります。ユーザーがいずれかのタイプの承認を拒否した場合、`HKError.Code.errorRequiredAuthorizationDenied`(エラー)が発生して承認に失敗します。**

## HealthKitデータへの許可要求

### アクセス許可要求 

HealthKitで利用する健康データとフィットネスデータには機密性の高い個人情報が含まれます。よって、ユーザーのプライバシーを保護するため、データにアクセスする前に許可要求を行う必要があります。

許可要求は、必要なデータにアクセスするタイミング毎に行うことが推奨されてます。以下に実装のサンプルを掲載します。(詳細は[Authorizing Access to Health Dataの『Request Permission from the User』](https://developer.apple.com/documentation/healthkit/authorizing_access_to_health_data)を参照してください。ソースコードとイメージは当該リンク先のものを抜粋してます。)

なお、許可を得ずにデータにアクセスした場合、 **アプリがクラッシュするので注意が必要** です。

``` swift
// 消費エネルギー、サイクリング、ウォーキング、ランニングの距離と心拍数の共有と読み出しに関する許可要求設定
let allTypes = Set([HKObjectType.workoutType(),
                    HKObjectType.quantityType(forIdentifier: .activeEnergyBurned)!,
                    HKObjectType.quantityType(forIdentifier: .distanceCycling)!,
                    HKObjectType.quantityType(forIdentifier: .distanceWalkingRunning)!,
                    HKObjectType.quantityType(forIdentifier: .heartRate)!])
// 許可要求を発行
self.healthStore.requestAuthorization(toShare: allTypes, read: allTypes) { (success, error) in
    if !success {
        // エラーが発生した場合の処理を実装
    }
}
```

![AccessPermissionRequest.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59827/b7430496-5c60-4e4f-2a75-31829a3c0f54.png)


### データ共有許可要求

HealthKitデータの保存前に、`authorizationStatus(for:)`を呼び出して、アプリが当該データを共有することを許可されているか確認(許可要求)を行う必要があります。許可要求を行わずに保存を行なった場合、`HKError.Code.errorAuthorizationNotDetermined`(エラー)で失敗します。
また、データ共有の設定が拒否の場合に保存を行うと、`HKError.Code.errorAuthorizationDenied`(エラー)で失敗します。

``` swift
let authorized = self.healthStore.authorizationStatus(for: sampleType)
```

## データの利用方法

HealthKitストアから歩数データの読み出す場合を例にHealthKitデータの利用方法を説明します。

``` swift
        // インスタンスの生成
        let healthStore = HKHealthStore()

        // 健康データ種別設定
        let type = Set([
            HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount )!
        ])

        // 許可要求を発行
        healthStore.requestAuthorization(toShare: [], read: type, completion: { success, error in

            if success == false {
                // エラー処理
            }

            // 健康データ読み出し
            let query = HKSampleQuery(sampleType: HKSampleType.quantityType(forIdentifier: .stepCount)!,
                                           predicate: HKQuery.predicateForSamples(withStart: fromDate, end: toDate, options: []),
                                           limit: HKObjectQueryNoLimit,
                                           sortDescriptors: [NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: true)]){ (query, results, error) in

                guard error == nil else { 
                                           // エラー処理
                                         }

                if let tmpResults = results as? [HKQuantitySample] {
                   // 当該箇所で取得したデータを表示用に加工等の処理
                }
            }
            healthStore.execute(query)
```

# ユーザーのプライバシー保護

健康データとフィットネスデータには、機密性の高い個人情報が含まれます。[Provide a Privacy Policy](https://developer.apple.com/documentation/healthkit/protecting_user_privacy)では、HealthKitを使ってアプリが当該データを扱うシーン毎に様々な定義がされてます。ここでは定義の詳細を紹介します。

- **暗号化されたデータへのアクセス**
- **アプリによる健康データの利用方法の明示**
- **プライバシーポリシーの提供**

## 暗号化されたデータへのアクセス

HealthKitデータへのアクセスに関して、以下定義がなされてます。

- ユーザーのデバイスは、すべてのHealthKitデータをローカルに保存します。セキュリティのために、ユーザーがデバイスをロックすると、デバイスはHealthKitストアを暗号化します。その結果、アプリがバックグラウンドで実行されている場合、アプリはストアからデータを読み取ることができない場合があります。
ただし、端末がロックされている場合でも、アプリはストアに書き込むことができます。HealthKitはデータを一時的にキャッシュし、ユーザーが携帯電話のロックを解除すると同時に暗号化されたストアに保存します。

## アプリによる健康データの利用方法の明示

「アプリは健康やフィットネスを目的とした使用でない限り、HealthKit APIにアクセスしてはならず、この使用方法がマーケティングテキストとユーザーインターフェースの両方で明確になっている必要がある。」と定義されています。

- アプリは、HealthKitフレームワークの使用によって得られた情報を広告または類似のサービスのために使用してはなりません。HealthKitフレームワークを使用するアプリで広告を配信することはできますが、HealthKitストアのデータを広告の配信に使用することはできないことに注意してください。

- ユーザーは、HealthKitを通じて得た情報を、ユーザーの明示的な許可なしに第三者に開示してはなりません。許可があっても、第三者に情報を共有できるのは、その第三者もユーザーに健康やフィットネスのサービスを提供している場合のみです。

- HealthKitを通じて得た情報を、広告プラットフォーム、データブローカー、情報再販業者に販売することはできません。

- ユーザーが同意した場合、医療研究のために第三者とHealthKitデータを共有することができます。

- アプリがHealthKitデータをどのように使用するかをユーザーに明確に開示する必要があります。

## プライバシーポリシーの提供

HealthKitを使用するアプリは、プライバシーポリシーを提示する必要があります。プライバシーポリシーの作成に関するガイダンスは、以下のサイトに掲載されています。([Provide a Privacy Policy](https://developer.apple.com/documentation/healthkit/protecting_user_privacy)より抜粋) **※5**

- Personal Health Record model (for non-HIPAA apps):[http://www.healthit.gov/policy-researchers-implementers/personal-health-record-phr-model-privacy-notice](http://www.healthit.gov/policy-researchers-implementers/personal-health-record-phr-model-privacy-notice)

- HIPAA model (for HIPAA covered apps):[http://www.hhs.gov/ocr/privacy/hipaa/modelnotices.html](http://www.hhs.gov/ocr/privacy/hipaa/modelnotices.html)

**※5 以下、[Provide a Privacy Policy](https://developer.apple.com/documentation/healthkit/protecting_user_privacy)より抜粋。**

ONC（Office of the National Coordinator for Health Information Technology）が開発したこれらのモデルは、アプリがどのようにユーザーデータを収集し共有するかを説明してます。これらのモデルは、Webベースのプライバシーポリシーに代わるものではなく、開発者は特定のアプリにどのモデルが適切であるかONCのガイダンスを参照する必要があります。 **これらのモデルは参考のためにのみ提供されており、Appleは、これらのモデルの使用に関するすべての責任を明示的に否認します。**

# HealthKitに関連する『App Store Review Guidlines』

[App Store Review Guidlines](https://developer.apple.com/app-store/review/guidelines/)では、ユーザーのプライバシー保護について以下事項が示されてます。

* 2.5.1 アプリはパブリックAPIのみを使用することができ、現在出荷されているOS上で実行する必要があります。
〜中略〜 HealthKitはヘルスケアとフィットネスの目的で、ヘルスケアAppに統合し使用される必要があります。

* 2.5.18 〜中略〜 Appで表示される広告は、そのAppの対象年齢に適したものであり、ユーザーをターゲットとした広告の場合、そのために使用された情報を使用中のAppを閉じることなくユーザーがすべて見ることができるようにする必要があります。なお、ヘルスケア/医療データ（例：HealthKit API）、学校/授業のデータ（例：ClassKit）、子どものデータ（例：「子ども向け」カテゴリのApp）など、機密性の高いユーザーデータに基づく追跡型広告や行動ターゲティング広告を組み込むことはできません。インタースティシャル広告や、ユーザーエクスペリエンスを中断させたり妨害したりする広告では、広告であることをはっきり明示する必要があります。また、広告をタップするようユーザーの行動を操ったり、だましたりすることはできません。ユーザーが広告を簡単に閉じられるよう、操作しやすく見やすい、十分な大きさの「閉じる」ボタンや「スキップ」ボタンを用意する必要があります。

* 5.1.2 データの使用と共有
    *  （vi）HomeKit API、HealthKit、Clinical Health Records API、MovementDisorder API、ClassKit、または深度測定ツールや（ARKit、Camera API、Photo APIなどの）フェイスマッピングツールで収集したデータを、サードパーティが行うものを含めて、マーケティング、広告、またはユーザーベースのデータマイニングに使用することは許可されません。CallKit、HealthKit、ClassKit、ARKitの実装におけるベストプラクティスについて詳しくは、リンク先をご確認ください。

* 5.1.3 健康および健康調査 健康、フィットネス、医療データは特に機密性が高く、この分野のアプリは顧客のプライバシーを確実に保護するためにいくつかの追加ルールを設けています。
    *  （i）健康、フィットネス、医療に関する調査のために収集されたデータを、許可を得た健康管理の向上または健康調査のため以外の目的（広告、マーケティング、またはその他のユーザーベースのデータマイニングなど）で、Appで使用またはサードパーティに公開することはできません。このデータは、Clinical Health Records API、HealthKit API、モーションとフィットネス、MovementDisorder API、健康関連の臨床調査から得られるデータなどを指します。ただし、ユーザーに直接メリット（より低額な保険料など）を提供する場合には、メリットを提供する組織によってAppが提出されており、データがサードパーティと共有されない限り、ユーザーの健康やフィットネスに関するデータをAppで使用することができます。その際、そのデバイスから収集される健康に関するデータについて具体的に明示する必要があります。
    * （ii）Appの使用によって、HealthKitまたはその他の健康調査Appや健康管理Appに虚偽のデータまたは誤ったデータが書き込まれないようにしてください。また、個人の健康情報をiCloudに保存することはできません。
    * （iii）健康に関する臨床調査を実施するAppでは、参加者本人、未成年の場合は親または保護者から同意を得る必要があります。このような同意には、（a）調査の性質、目的、期間、（b）手順、患者へのリスクおよび利点、（c）データの機密性と扱いに関する情報（サードパーティとの共有を含む）、（d）患者が質問がある場合の連絡先、（e）辞退プロセスを含める必要があります。
    *  （iv）健康関連の臨床調査を実施するAppは、独立した倫理審査委員会の適切な承認を得る必要があります。承認を受けた証拠を要望に応じて提示していただく必要があります。

# HealthKitに関連する『Human Interface Guidelines』

[Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/technologies/healthkit)では、ユーザーのプライバシー保護について以下事項が示されてます。

- あなたのアプリが健康やフィットネスの機能を提供しない場合、人々の個人的な健康データへのアクセスを要求しないでください。
- 人々のデータにアクセスするためには許可を得る必要があり、そのデータを保護するために必要なすべての措置を講じる必要があります。許可を得た後も、データの使用方法を明確に示すことで、人々の信頼を維持することが重要です。
- アプリの提出プロセスでは、プライバシーポリシーを明示したURLを提供し、ユーザーがアプリのApp Storeページでリンクをクリックすると、そのポリシーが表示されるようにする必要があります。
- 健康データへのアクセスは、必要なときだけ要求します。例えば、人々が体重を記録するときに体重情報へのアクセスを要求することは意味がありますが、アプリの起動直後には要求しないでください。要求が現在のコンテキストに明確に関連している場合、アプリの意図を理解してもらうことができます。また、ユーザーは付与した権限を変更できるため、アプリはアクセスが必要になるたびにリクエストを行う必要があります。
- 健康データの共有は、システムのプライバシー設定を通じてのみ管理する。人々は、設定＞プライバシーで自分の健康情報へのアクセスをグローバルに管理することを期待しています。健康データの流れに影響を与えるような画面をアプリに追加して、人々を混乱させないようにしましょう。

# 記事執筆で参考にした情報

本記事を執筆する上で参考にした書籍、サイトを掲載します。

- [HealthKit](https://developer.apple.com/documentation/healthkit)
- [Developer Mode](https://developer.apple.com/documentation/xcode/enabling-developer-mode-on-a-device)
- [Specify How Your App Uses the Health Data](https://developer.apple.com/documentation/healthkit/protecting_user_privacy)
- [Provide a Privacy Policy](https://developer.apple.com/documentation/healthkit/protecting_user_privacy)
- [App Store Review Guidlines](https://developer.apple.com/app-store/review/guidelines/)
- [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/technologies/healthkit)
- [What's new in HealthKit](https://developer.apple.com/videos/play/wwdc2022/10005/)

# 最後に

最後まで読んで頂き、ありがとう御座います。
13日目となる明日の記事も楽しみにして頂ければと思います。