Swift iOS HealtKitからヘルスデータ(体重など)を取得する
1.HealthKitからデータを読む
HealthKitを使用する準備ができたので、実際にデータを取得してみる。
サンプルアプリの動作が上の動画。各種チェック結果をラベルに表示、ヘルスデータへのアクセスを許可し、体重を取得する。
いろいろ、ドキュメントを見て概要を把握しながら実施した結果こコードが以下。
調べたメモは後半に。
大枠のながれとサンプルソース
- checkHealthKit() : HealtKitが使用可能かチェック
- onAccessRequest() : ヘルスデータへのアクセス許可を得る
- getBodyMass() : ヘルスデータから体重情報を取得し画面に表示
import HealthKit import UIKit class ViewController: UIViewController { var isHealthAvailable : Bool! var healthStore : HKHealthStore! @IBOutlet weak var enabledHealthKitLabel: UILabel! @IBOutlet weak var healthStoreLabel: UILabel! @IBOutlet weak var requestResultLabel: UILabel! @IBOutlet weak var queryStatusLabel: UITextView! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. self.queryStatusLabel.layer.borderColor = UIColor.blue.cgColor self.queryStatusLabel.layer.borderWidth = 1.0 checkHealthKit() } @IBAction func onAccessRequest(_ sender: Any) { let allTypes = Set([ HKQuantityType.quantityType(forIdentifier: .bodyMass)!, HKQuantityType.quantityType(forIdentifier: .stepCount)!, ]) self.healthStore.requestAuthorization(toShare: allTypes, read: allTypes) { (success, error) in var result = "" if success { result = "アクセス許可: \(String(describing: success))" } else { result = "\(String(describing: error?.localizedDescription))" } DispatchQueue.main.async { self.requestResultLabel.text = result } } } func checkHealthKit() { self.isHealthAvailable = HKHealthStore.isHealthDataAvailable() self.enabledHealthKitLabel.text = "Healthデータ利用 : \(self.isHealthAvailable!)" if self.isHealthAvailable { healthStore = HKHealthStore() } healthStoreLabel.text = "HealthStore : \(String(describing: self.healthStore))" } @IBAction func getBodyMass(_ sender: Any) { let start = Calendar.current.date(byAdding: .month, value: -48, to: Date()) let end = Date() let predicate = HKQuery.predicateForSamples(withStart: start, end: end) let sampleType = HKQuantityType.quantityType(forIdentifier: .bodyMass)! let query = HKSampleQuery( sampleType: sampleType, predicate: predicate, limit: HKObjectQueryNoLimit, sortDescriptors: nil) { (query, results, error) in let samples = results as! [HKQuantitySample] var buf = "" for sample in samples { // Process each sample here. let s = sample.quantity print("\(String(describing: sample))") buf.append("\(sample.startDate) \(String(describing: s))\n") } DispatchQueue.main.async { self.queryStatusLabel.text = "\(buf)" } } self.healthStore.execute(query) } }
2.HealthKit Storeからデータにアクセスする方法
HealthKit Storeからデータにアクセスする方法は、主に以下の3つです。
- メソッドを直接呼び出す HealthKitストアは、特性データに直接アクセスするためのメソッドを提供します。
- これらのメソッドは、特性データへのアクセスにのみ使用できます。詳細については、HKHealthStoreを参照してください。
- クエリ。クエリーは、要求されたデータの現在のスナップショットをHealthKitストアから返します。
- 長時間実行されるクエリ。これらのクエリはバックグラウンドで実行され続け、HealthKitストアに変更が加えられるたびにアプリを更新します。
2.1 クエリー
- クエリーは、HealthKitストア内のデータの現在のスナップショットを返します。
- クエリーが完了すると、バックグラウンド・キュー上で結果ハンドラを実行します。
- HealthKitはさまざまなタイプのクエリを提供し、それぞれがHealthKitストアからさまざまな種類のデータを返すように設計されています。
- HKQueryクラスは、HealthKitストアからデータを取得するすべてのクエリ オブジェクトの基礎となるクラスです。
- HKQueryクラスは抽象クラスです。HKQueryクラスを直接インスタンス化することはできません。その代わり、必ず具象サブクラスのいずれかを使用します。
- HKQueryクラスの具象サブクラス(HKSampleQuery、HKAnchoredObjectQuery、HKCorrelationQuery、HKObserverQuery、HKSourceQuery、HKStatisticsQuery、またはHKStatisticsCollectionQueryのいずれかのクラス)です。
2.1.1 サンプルクエリ(HKSampleQuery)
- 汎用的なクエリです。サンプルクエリを使用して、あらゆるタイプのサンプルデータにアクセスできます。
- サンプルクエリは、結果をソートしたり、返されるサンプルの総数を制限したりしたい場合に特に便利です。
- サンプル クエリを使用すると、HKCategorySample、HKCorrelation、HKQuantitySample、および HKWorkout オブジェクトなど、HKSample クラスの任意の具象サブクラスを検索することができます。
- サンプル クエリは、指定された型と述語に一致するサンプル オブジェクトを返します。返されるサンプルの並べ替え順序を指定したり、返されるサンプル数を制限することができます。他のクエリクラスを使用すると、より特殊な検索や計算を行うことができます
2.1.2 アンカー付きオブジェクトクエリ(HKAnchoredObjectQuery)
- ストアに追加された項目やストアから削除された項目を検索するために使用します。
- アンカー クエリを最初に実行すると、現在ストアにある一致するすべてのサンプルが返されます。
- それ以降の実行では、前回の実行以降に追加または削除された項目のみが返されます。
2.1.3 統計クエリ(HKStatisticsQuery)
- このクエリを使用して、一致するサンプルのセットに対して統計計算を実行します。
- 統計クエリを使用して、セット内の合計値、最小値、最大値、または平均値を計算することができます。
2.1.4 統計コレクションクエリ(HKStatisticsCollectionQuery)
- このクエリを使用すると、一連の固定長の時間間隔にわたって複数の統計クエリを実行できます。
- これらのクエリは、グラフを作成するときによく使用します。
- このクエリを使用すると、1日の総消費カロリーや5分間隔の歩数などを簡単に計算することができます。
2.1.5 相関クエリ(HKCorrelationQuery)
- このクエリを使用すると、相関関係に含まれるデータの複雑な検索を実行できます。
- これらのクエリには、相関に保存されているサンプル タイプのそれぞれについて、個別の述語を含めることができます。
- 相関タイプに一致させるだけなら、代わりにサンプル クエリを使用します。
2.1.6 ソースクエリ(HKSourceQuery)
- このクエリを使用して、一致するサンプルをHealthKitストアに保存しているソース(アプリとデバイス)を検索します。
- ソースクエリは、特定のサンプルタイプを保存しているすべてのソースを一覧表示します。
2.1.7 アクティビティ サマリー クエリ(HKActivitySummaryQuery)
- このクエリーを使用して、ユーザーのアクティビティサマリー情報を検索します。
- 各アクティビティ・サマリー・オブジェクトには、特定の日のユーザー・アクティビティのサマリーが含まれています。
- 1日または日数範囲のいずれかを指定してクエリを実行することができます。
2.1.8 ドキュメントクエリ(HKDocumentQuery)
- このクエリを使用して、健康に関するドキュメントを検索します。
2.2 ロングランクエリ
- 長時間実行されるクエリは、匿名のバックグラウンドキューを実行し続け、HealthKitストアに変更が加えられるたびにアプリを更新します。
- さらに、オブザーバークエリーはバックグラウンド配信に登録することができます。
- 更新が行われるたびにHealthKitがバックグラウンドでアプリを起動するようになります。
2.2.1 オブザーバークエリ(HKObserverQuery)
- この長時間クエリは、HealthKitストアを監視し、一致するサンプルに変更があった場合に警告を発します。
- ストアの変更について通知を受けたい場合は、オブザーバークエリを使用します。
- バックグラウンド配信のためにオブザーバークエリを登録することができます。
2.2.2 アンカー付きオブジェクトクエリ(HKAnchoredObjectQuery)
- アンカー付きオブジェクトクエリは、変更されたデータの現在のスナップショットを返すだけでなく、長時間実行するクエリとして機能することができます。
- 有効にすると、バックグラウンドで実行され、一致するサンプルがストアに追加またはストアから削除されると更新が提供されます。
- オブザーバークエリとは異なり、これらの更新には追加または削除されたアイテムのリストが含まれます。
- アンカーオブジェクトクエリはバックグラウンド配信に登録することはできません。
2.2.3 統計情報収集クエリ(HKStatisticsCollectionQuery)
- 統計コレクションの現在のスナップショットを計算するだけでなく、このクエリは長期的なクエリとして機能することができます。
- 一致するサンプルがストアに追加またはストアから削除された場合、このクエリは統計コレクションを再計算し、アプリを更新します。
- 統計コレクションクエリをバックグラウンド配信に登録することはできません。
2.2.4 アクティビティサマリークエリ(HKActivitySummaryQuery)
- このクエリは、ユーザーのアクティビティサマリーの現在のスナップショットを計算するだけでなく、長時間実行可能なクエリとして機能します。
- ユーザーのアクティビティサマリーのデータが変更された場合、このクエリーはアクティビティサマリーを再計算し、アプリを更新します。
- アクティビティサマリーのクエリーは、バックグラウンド配信に登録することはできません。
2.3 結果タイプと種類
2.3.1 HKQuantityType
- HKCharacteristicType
- 時間の経過とともに変化することのないデータを表す型。
- HKCategoryType
- ある値を含むサンプルを少数の可能な値の集合から識別するタイプ。
- HKCorrelationType
- 複数のサブサンプルをグループ化したサンプルを識別するためのタイプ。
- HKActivitySummaryType
- アクティビティサマリーオブジェクトを識別するための型。
- HKAudiogramSampleType (オーディオグラムサンプルタイプ)
- オーディオグラムデータを含むサンプルを識別するためのタイプ。
- cHKElectrocardiogramType – 心電図タイプ。
- 心電図データを含むサンプルを識別するためのタイプ。
- HKSeriesType
- シリーズサンプルに格納されているデータを示すタイプです。
- HKClinicalType
- 臨床記録データを含むサンプルを識別するためのタイプです。
- HKWorkoutType
- ワークアウトに関する情報を格納するサンプルを識別するためのタイプです。
- HKObjectType
- HealthKitストアの特定のデータ型を識別するサブクラスを持つ抽象的なスーパークラスです。
- HKSampleType
- HealthKitストアで作業する際に、特定のタイプのサンプルを識別するすべてのクラスの抽象的なスーパークラスです。
2.3.2 HKQuantityTypeIdentifier
Activity
- static let stepCount: HKQuantityTypeIdentifier
- ユーザーが歩いた歩数を計測する量的サンプルタイプです。
- static let distanceWalkingRunning: HKQuantityTypeIdentifier
- ユーザーが歩いたり走ったりして移動した距離を測定する量的サンプルタイプです。
- static let distanceCycling: HKQuantityTypeIdentifier
- ユーザーが自転車で移動した距離を測定する量的サンプルタイプです。
- static let pushCount: HKQuantityTypeIdentifier
- ユーザーが車椅子を使用している時に行った押しの回数を測定する量的サンプルタイプです。
- static let distanceWheelchair: HKQuantityTypeIdentifier
- ユーザーが車椅子を使用して移動した距離を測定する量的サンプルタイプです。
- static let swimmingStrokeCount: HKQuantityTypeIdentifier
- 水泳で行ったストローク数を測定する量的サンプルタイプです。
- static let distanceSwimming: HKQuantityTypeIdentifier 水泳の距離を測定する量的サンプルタイプ。
- 水泳中に移動した距離を測定する量的サンプルタイプです。
- static let distanceDownhillSnowSports: HKQuantityTypeIdentifier
- ユーザーがスキーやスノーボードで移動した距離を測定する量的サンプルタイプです。
- static let basalEnergyBurned: HKQuantityTypeIdentifier
- ユーザーが消費した安静時のエネルギーを測定する量的サンプルタイプです。
- static let activeEnergyBurned: HKQuantityTypeIdentifier
- ユーザーが消費したアクティブエネルギーの量を測定するサンプル量タイプです。
- static let flightsClimbed: HKQuantityTypeIdentifier
- ユーザーが登った階段の便数を測定する量的サンプルタイプです。
- static let nikeFuel: HKQuantityTypeIdentifier
- ユーザーが獲得したNikeFuelポイントの数を測定する量的サンプルタイプです。
- static let appleExerciseTime: HKQuantityTypeIdentifier ユーザーが獲得した NikeFuel ポイント数を測定する量的サンプルタイプです。
- ユーザーがエクササイズに費やした時間を測定する量的サンプルタイプです。
- static let appleStandTime: HKQuantityTypeIdentifier ユーザーが運動した時間を測定する量的サンプルタイプです。
- ユーザーが立っていた時間を測定する量的サンプルタイプです。
- static let vo2Max: HKQuantityTypeIdentifier
- 運動中の最大酸素消費量を測定する量的サンプルです。 無料版のDeepL翻訳(www.DeepL.com/Translator)で翻訳しました。
身体測定値
- static let height: HKQuantityTypeIdentifierです。
- ユーザーの身長を測定する量的サンプルタイプです。
- static let bodyMass: HKQuantityTypeIdentifier
- ユーザーの体重を測定する量的サンプルタイプです。
- static let bodyMassIndex: HKQuantityTypeIdentifier
- ユーザーのボディマス指数を測定する量的サンプルタイプです。
- static let leanBodyMass: HKQuantityTypeIdentifier
- ユーザーの除脂肪体重を測定する量的サンプルタイプです。
- static let bodyFatPercentage: HKQuantityTypeIdentifier ユーザーの体脂肪率を測定する量的サンプルタイプです。
- ユーザーの体脂肪率を測定するサンプル量タイプです。
- static let waistCircumference: HKQuantityTypeIdentifier
- ユーザーのウエスト周囲径を測定するサンプル量タイプです。
リプロダクティブヘルス
- static let basalBodyTemperature: HKQuantityTypeIdentifier
- ユーザーの基礎体温を記録する量的サンプルタイプです。
ヒアリング
- static let environmentalAudioExposure: HKQuantityTypeIdentifier
- 環境音へのオーディオ暴露を測定する量的サンプルタイプ。
- static let headphoneAudioExposure: HKQuantityTypeIdentifier
- ヘッドホンからの音声暴露を測定する量的サンプルタイプです。
バイタルサイン
- static let heartRate: HKQuantityTypeIdentifier
- ユーザーの心拍数を測定する量的サンプルタイプです。
- static let restingHeartRate: HKQuantityTypeIdentifier
- ユーザーの安静時の心拍数を測定する量的サンプルタイプです。
- static let walkingHeartRateAverage.HKQuantityTypeIdentifier(静的レットウォーキングハートレートアベレージ)。HKQuantityTypeIdentifier
- 歩行中のユーザーの心拍数を測定するサンプル量タイプです。
- static let heartRateVariabilitySDNN: HKQuantityTypeIdentifier
- 心拍間隔の標準偏差を測定する量的サンプルタイプです。
- static let oxygenSaturation: HKQuantityTypeIdentifier
- ユーザーの酸素飽和度を測定するサンプル量タイプです。
- static let bodyTemperature: HKQuantityTypeIdentifier
- ユーザーの体温を測定するサンプル量タイプです。
- static let bloodPressureDiastolic: HKQuantityTypeIdentifier ユーザーの体温を測定するサンプル量タイプです。
- ユーザーの拡張期血圧を測定するサンプル量タイプです。
- static let bloodPressureSystolic: HKQuantityTypeIdentifier ユーザーの拡張期血圧を測定するサンプル量タイプです。
- ユーザーの収縮期血圧を測定するサンプル量タイプです。
- static let respiratoryRate: HKQuantityTypeIdentifier
- ユーザーの呼吸数を測定するサンプル量タイプです。
モビリティ
- static let appleWalkingSteadiness: HKQuantityTypeIdentifier
- ユーザーの歩行の安定性を測定する量的サンプルタイプです。
- static let sixMinuteWalkTestDistance: HKQuantityTypeIdentifier
- ユーザーが6分間の歩行テストで歩ける距離を格納する量的サンプルタイプです。
- static let walkingSpeed: HKQuantityTypeIdentifier
- 平坦な場所を安定して歩くときのユーザーの平均速度を測定する量的サンプルタイプです。
- static let walkingStepLength: HKQuantityTypeIdentifier (静的レットウォーキングステップレングス:HKQuantityTypeIdentifier)。
- 平坦な地面を安定して歩くときの、ユーザーの平均歩幅を測定するサンプル量タイプです。
- static let walkingAsymmetryPercentage: HKQuantityTypeIdentifier
- 平坦な地面を歩行する際、片足がもう片方の足と異なる速度で動く歩幅の割合を測定する量的サンプルタイプです。
- static let walkingDoubleSupportPercentage: HKQuantityTypeIdentifier
- 平坦な地面を安定して歩いているときに、ユーザーの両足が地面に触れている時間の割合を測定する量的サンプルタイプです。
- static let stairAscentSpeed: HKQuantityTypeIdentifier
- 階段を登っているときのユーザーの速度を測定する量的サンプルタイプです。
- static let stairDescentSpeed: HKQuantityTypeIdentifier
- 階段を下りているときのユーザーの速度を測定するサンプル量タイプです。
2.3.3 条件
NSPredicate
述語は論理的な条件を表し、それを使ってオブジェクトのコレクションをフィルタリングすることができます。NSComparisonPredicate、NSCompoundPredicate、NSExpressionのインスタンスから直接述語を作るのが一般的ですが、クラスメソッドがNSPredicateをパースするフォーマット文字列から述語を作ることもよくあります。述語のフォーマット文字列の例は、以下を含みます。
- 単純な比較、例えば、grade == “7” or firstName like “Juan”
- 大文字と小文字を区別しない検索、例えば、name contains[cd] “stein”
- (firstName like “Mei”) OR (lastName like “Chen”)のような論理演算。
- date between {$YESTERDAY, $TOMORROW}のような時間的な範囲制約
- group.name like “work*”のような関係条件
- sum.items.price < 1000のような集計処理
3.サンプルクエリの実行
https://developer.apple.com/documentation/healthkit/hksamplequery/executing_sample_queries
https://qiita.com/sato-shin/items/a1b6026359d340afe91b
HealthKitストアからサンプルを読み込むには、サンプルクエリを使用します。各クエリーは、歩数や心拍数など、1種類のサンプルを返します。述語を使用して結果をさらにフィルタリングしたり、ソート記述子を使用して結果を並べ替えたりすることができます。
init(sampleType:predicate:limit:sortDescriptors:resultsHandler:) というイニシャライザーを呼び出して、サンプルクエリを作成します。まず、サンプルタイプを作成します。
guard let sampleType = HKSampleType.quantityType(forIdentifier: HKQuantityTypeIdentifier.dietaryEnergyConsumed) else { fatalError(“
- This method should never fail
*”) }
次に、クエリ自体を作成します。このクエリーは、すべての食事エネルギー消費量のサンプルを返す。その結果ハンドラは、サンプルを処理する前にあらゆるエラーをチェックし、ユーザーインターフェースの更新をメインキューにディスパッチする。
let query = HKSampleQuery(sampleType: sampleType, predicate: nil, limit: Int(HKObjectQueryNoLimit), sortDescriptors: nil) { query, results, error in
guard let samples = results as? [HKQuantitySample] else {
// Handle any errors here.
return
}
for sample in samples {
// Process each sample here.
}
// The results come back on an anonymous background queue.
// Dispatch to the main queue before modifying the UI.
DispatchQueue.main.async {
// Update the UI here.
}
}
クエリをインスタンス化した後、HealthKitストアのexecute(_:)メソッドを呼び出して実行します。
store.execute(query)
このメソッドは、匿名のバックグラウンドキューでクエリを実行します。クエリが完了すると、同じバックグラウンドキューで結果ハンドラを実行します (ただし、同じスレッドである必要はありません)。