【Swift】HealthKitの使い方!ヘルスケア/フィットネスデータの取得

【Swift】HealthKitの使い方!ヘルスケア/フィットネスデータの取得

この記事からわかること

  • Swift/iOSHealthKitフレームワーク使い方
  • ヘルスケア/フィットネスデータ取得
  • HKHealthStoreクラスとは?
  • 消費カロリー歩数ランニングデータ、睡眠心拍などの取得方法

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

環境

HealthKitとは?

HealthKit」とはiOS・watchOSにおいて健康データやフィットネスデータを管理、表示、共有機能など提供するフレームワークです。HealthKitフレームワークを使用することでデフォルトで入っている「ヘルスケア」や「フィットネス」アプリのデータを参照できるようになります。開発したアプリからデータを参照するためにはユーザーの明示的な許可が必要になります。

※ ワークアウトとはウォーキングやランニングなど特定の運動のパフォーマンスデータを追跡するための活動セッションのことです。Apple Watchには「ワークアウト」アプリがあり特定の運動を計測することが可能です。

【Swift】HealthKitの導入方法と使い方!

引用 公式リファレンス:HealthKit

HealthKitアプリを開発する前準備

公式リファレンス:HealthKitの設定

開発アプリからHealthKitを使用できるようにするためのプロジェクト側の設定を行っていきます。まず「General」>「Frameworks,Libraries,and Embedded Content」から「HealthKit」と「HealthKitUI」を追加します。

【Swift】HealthKitの導入方法と使い方!

続いて「Signing & Capabilities」から「HealthKit」を追加します。アプリから「Clinical Health Records(臨床健康記録)」を参照したい場合のみ「Clinical Health Records」にチェックを入れておきます。チェック済みなのにアプリからデータを参照しない場合はリジェクトされる可能性もあるので注意してください。

【Swift】HealthKitの導入方法と使い方!

info.plistに権限の追加

続いて「info.plist」にデータの読み取りや書き込み権限を追加し、説明を記述しておきます。適切に説明を追加しておかないとデータへのアクセス承認を実行時にアプリがクラッシュしてしまいます。

【Swift】HealthKitの導入方法と使い方!

※ 臨床データを取得したい場合のみ追加する必要があります。

これで準備が整いました。ここからは開発方法をまとめていきます。実装サンプルコードはGitHubで公開しているので参考にしてください。

HealthKitの主要なクラス

HealthKitで実装するために主要となるクラスなどを先に軽くまとめておきます。

HealthKit Store

HealthKitのデータはiPhone・Apple Watch・visionOSごとに独立したHealthKit Storeに管理されています。独立はしていますがデバイス間でデータを自動的に同期しているので共通したデータを参照することができるようになっておりHKHealthStoreクラスとして定義されています。Apple Watchではスペースを節約するために定期的に古いデータは削除される仕様になっておりされる仕様になっておりearliestPermittedSampleDate()メソッドを使用して最古のデータを参照することができるようになっています。

HKObject

HKObjectHealthKitデータのスーパークラスです。後述するHKCharacteristicHKSampleなどが継承しているクラスでデータベースのメタ情報などの保持を義務つげます。

HKCharacteristic

HKCharacteristic時間共に変化しないデータの型です。主に誕生日や血液型、生年月日などを取得できます。

HKSample

HKSample時間共に変化するデータの型です。開始時間と終了時間を明示的に指定して期間内のデータを取得します。HKSampleもスーパークラスとして定義されており後述するなどが継承しています。

HKQuantitySample

HKQuantitySampleHKSampleを継承したクラスで値を数値で取得できるようなデータの型です。主に歩数や消費カロリー、移動距離などを取得できます。

HKCategorySample

HKCategorySampleHKSampleを継承したクラスでカテゴリに分類できるようなデータの型です。主に睡眠分析や生理、食欲の変化などを取得できます。

HKSampleQuery

HKSampleQueryHKSampleを継承しているヘルスケアデータを取得するためのクエリオブジェクトです。取得したいデータ項目や期間、数量などを指定することができます。

データへの許可要求

公式リファレンス:健康データへのアクセスの許可

HealthKitのデータはユーザーのプライバシーを保護するために認証なしに参照することができない仕様になっています。許可申請は読み取り/書き込みのデータごとに細かく申請できるようになっておりリクエストを実行する際に必要なデータタイプを指定する必要があります。この許可申請は一括で行うことも可能ですが、実際にデータが必要になるタイミングでの申請が公式からは推奨されています。

データごとの許可項目はHKCharacteristicTypeHKQuantityTypeのイニシャライザなどから取得できます。許可申請したい項目をSetでまとめておきrequestAuthorization(toShare:read:)メソッドを使用して要求を出します。

/// 書き込み許可申請項目
public let writeAllTypes: Set = [
    // 歩数
    HKQuantityType(.stepCount),
    // 消費エネルギー
    HKQuantityType(.activeEnergyBurned),
    // サイクリングの移動距離
    HKQuantityType(.distanceCycling),
    // ウォーキング・ランニングの移動距離
    HKQuantityType(.distanceWalkingRunning),
    // 車椅子ユーザーの移動距離
    HKQuantityType(.distanceWheelchair),
    // 心拍数
    HKQuantityType(.heartRate),
    // ワークアウト
    HKQuantityType.workoutType()
]
    
/// 読み取り許可申請項目
public let readAllTypes: Set = [
    // 性別
    HKCharacteristicType(.biologicalSex),
    // 血液型
    HKCharacteristicType(.bloodType),
    // 誕生日
    HKCharacteristicType(.dateOfBirth),
    // 歩数
    HKQuantityType(.stepCount),
    // 消費エネルギー
    HKQuantityType(.activeEnergyBurned),
    // サイクリングの移動距離
    HKQuantityType(.distanceCycling),
    // ウォーキング・ランニングの移動距離
    HKQuantityType(.distanceWalkingRunning),
    // 車椅子ユーザーの移動距離
    HKQuantityType(.distanceWheelchair),
    // 心拍数
    HKQuantityType(.heartRate),
    // ワークアウト
    HKQuantityType.workoutType()
]

isHealthDataAvailable対象デバイスがそもそもHealthKitが有効なデバイスかどうかを識別できます。requestAuthorization(toShare:read:)にはtoShareに書き込み対象をSet<HKSampleType>readには読み取り対象をSet<HKObjectType>で渡します。ただプライバシー保護の一環で許可申請の承認/拒否はアプリから識別はできないようです。

/// HealthKit許可申請要求
private func requestAuthorization() async {
    do {
        // HealthKitが有効なデバイスかどうか
        guard HKHealthStore.isHealthDataAvailable() else { return }
        // 許可申請要求
        // プライバシー保護の一環で許可申請の承認/拒否はアプリから識別はできない
        try await healthStore.requestAuthorization(toShare: writeAllTypes, read: readAllTypes)
    } catch {
        // 失敗するのはアプリのInfo.plistの設定不足
        // もしくは現在のデバイスで健康データが利用できない場合
        fatalError("承認を要求中に予期しないエラーが発生しました: \(error.localizedDescription)")
    }
}

このメソッドを実行すると以下のように指定した項目に許可チェックを行えるシートが起動します。

【Swift】HealthKitの導入方法と使い方!

HealthKitデータの取得

HealthKitデータを取得する際にアクセス許可が承諾されていない場合は以下のようなエラーが発生します。

Error Domain=com.apple.healthkit Code=5 "Authorization is not determined" UserInfo={NSLocalizedDescription=Authorization is not determined}

HKCharacteristicデータ

HKCharacteristicデータを取得したい場合はHKHealthStoreから各項目のメソッドから取得することができます。例えば性別ならbiologicalSexメソッドのbiologicalSexプロパティからHKBiologicalSex型で取得できます。

/// 特性情報を取得
public func readCharacteristic() {
    // 性別を取得
    guard let biologicalSex = try? healthStore.biologicalSex().biologicalSex else { return }
    switch biologicalSex {
    case .female:
        print("性別: 女性")
    case .male:
        print("性別: 男性")
    case .other:
        print("性別: その他")
    case .notSet:
        print("性別: 未設定")
    @unknown default:
        print("性別: 不明")
    }
    
    // 年齢を計算
    guard let dateOfBirth = try? healthStore.dateOfBirthComponents().date else { return }
    let calendar = Calendar.current
    let now = Date()
    let ageComponents = calendar.dateComponents([.year], from: dateOfBirth, to: now)
    guard let age = ageComponents.year else { return }
    print("年齢: \(age) 歳")

    // 血液型を取得
    guard let bloodType = try? healthStore.bloodType().bloodType else { return }
    switch bloodType {
    case .aPositive:
        print("血液型: A+")
    case .aNegative:
        print("血液型: A-")
    case .bPositive:
        print("血液型: B+")
    case .bNegative:
        print("血液型: B-")
    case .abPositive:
        print("血液型: AB+")
    case .abNegative:
        print("血液型: AB-")
    case .oPositive:
        print("血液型: O+")
    case .oNegative:
        print("血液型: O-")
    case .notSet:
        print("血液型: 未設定")
    @unknown default:
        print("血液型: 不明")
    }
}

HKSampleデータ

HealthKitデータは項目ごとにHKSampleQueryを定義してexecuteメソッドを使用して実行します。

public func reading() {
    // 昨日の開始時刻と終了時刻を計算
    let calendar = Calendar.current
    // 昨日の開始時刻
    let startOfYesterday = calendar.startOfDay(for: Date().addingTimeInterval(-86400))
    // 昨日の終了時刻(開始時刻 + 1日)
    guard let endOfYesterday = calendar.date(byAdding: .day, value: 1, to: startOfYesterday) else { return }
    
    // 取得したいデータタイプ
    let type = HKQuantityType(.activeEnergyBurned)
    // 取得対象期間 Date型
    let predicate = HKQuery.predicateForSamples(withStart: startOfYesterday, end: endOfYesterday, options: [])
    // 取得数制限 HKObjectQueryNoLimit = 無制限
    let limit = HKObjectQueryNoLimit
    // 並び順
    let sort = [NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: true)]
    
    // データ読み出しクエリ
    let query = HKSampleQuery(
        sampleType: type,
        predicate: predicate,
        limit: limit,
        sortDescriptors: sort
    ) { [weak self] (query, results, error) in
        guard let self else { return }
        guard error == nil else { return }
        guard let tmpResults = results as? [HKQuantitySample]  else { return }
        // 総カロリーを計算
        let totalEnergyBurned = tmpResults.reduce(0.0) { sum, sample in
            return sum + sample.quantity.doubleValue(for: .kilocalorie())
        }
        print("総消費カロリー: \(totalEnergyBurned) kcal")
        self.kilocalorie = totalEnergyBurned
    }
    // クエリ実行
    healthStore.execute(query)
}

HKSampleQueryに引数にはそれぞれ以下の項目を渡す必要があり、結果は[HKSample]?型で取得することができます。

プライバシー保護について

公式リファレンス:ユーザーのプライバシーの保護

HealthKitデータに関してはプライバシーに関する制約がきめ細かく、ユーザーからのアクセスの承認も項目ごとにできると説明しました。それだけでなく公式ドキュメントにはプライバシーに関する情報はいくつか記述されています。

データの暗号化

HealthKitデータは端末にローカル保存されています。ユーザーがデバイスをロックしている際にはHealthKitデータは暗号化されるためバックグラウンド環境からデータを読み取れない可能性があるようです。ただロックされていても書き込み自体は問題なく行えるようです。

アプリ内での明示的な利用表示

HealthKitの利用はApple公式から適切な場合かつ明示的な利用方法の開示をした上でないと利用できないと記述されています。

さらにHealthKitを使用したアプリには次のガイドラインが適用されるようです。

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

HealthKitフレームワークを使用する全てのアプリはプライバシーポリシーを提供する必要があります。プライバシーポリシーの作成に関するガイダンスは以下サイトを参照。

個人健康記録モデル(HIPAA 非準拠アプリ用)
HIPAA モデル (HIPAA 対象アプリの場合)

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index