HealthKitデータの管理と同期を行うためのクラス
このコードは、HealthKitデータの管理と同期を行うためのクラス HealthKitStore
とそれに関連するプロトコル HealthKitStoreProtocol
を定義しています。このクラスは、HealthKitフレームワークを使用してユーザーのヘルスデータを読み取り、アップロードするための機能を提供します。
import Foundation
import HealthKit
import UIKit
import Combine
protocol HealthKitStoreProtocol {
func authorizeHealthKit(completion: @escaping () -> Void)
func startObservingDataChanges(queue: DispatchQueue?, isBackgroundTask: Bool, completion: @escaping () -> Void)
func updateCharacteristicIdentifiers()
func getMostRecentHealthKitSample<T>(for sampleType: HKSampleType,
completion: @escaping ([T], Date, Error?) -> Void) where T: HKSample
}
class HealthKitStore: HealthKitStoreProtocol {
static let firstStartDateInterval: Double = -90*24*3600
static let typeEcgVoltage = "HKQuantityTypeIdentifierECGVoltage"
static let typeElectrocardiogramType = HKSampleType.electrocardiogramType().identifier
private var userDefault: UserDefaultUtilsProtocol
private var localDatabase: LocalDatabaseProtocol
private var dataSyncService: DataSyncServiceProtocol
let healthKitStore:HKHealthStore = HKHealthStore()
private var blockIdentifier: [String: Bool] = [:]
private var isHealkitLoadingData: Bool = false
private var group = DispatchGroup()
private var uploadDatas: [UploadFileDataModel] = []
private var sendingIdentifier: [String: Date] = [:]
private var activeQueries: [HKQuery] = []
private var queue: DispatchQueue = DispatchQueue(label: "bgTask")
private var stores = Set<AnyCancellable>()
static let healthKitCharacteristicType = [
HKObjectType.characteristicType(forIdentifier: HKCharacteristicTypeIdentifier.biologicalSex)!,
HKObjectType.characteristicType(forIdentifier: HKCharacteristicTypeIdentifier.wheelchairUse)!,
]
public static var healthKitActivityType: [HKSampleType] {
var list = [
//省略
]
if #available(iOS 16, *) {
list.append(HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.atrialFibrillationBurden)!)
list.append(HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRateRecoveryOneMinute)!)
}
return list
}
static let healthKitEventType = [
HKCategoryType(.appleWalkingSteadinessEvent),
HKCategoryType(.lowHeartRateEvent),
HKCategoryType(.highHeartRateEvent),
HKCategoryType(.irregularHeartRhythmEvent)
]
static let healthKitCategoryType = [
HKObjectType.categoryType(forIdentifier: HKCategoryTypeIdentifier.sleepAnalysis)!
]
public static var mapHealthKitActivityUnit: [HKSampleType: HKUnit] {
var list = [
//省略
]
if #available(iOS 16, *) {
list[HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.atrialFibrillationBurden)!] = HKUnit.percent()
list[HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRateRecoveryOneMinute)!] = HKUnit(from: "count/min")
}
return list
}
init(userDefault: UserDefaultUtilsProtocol,
localDatabase: LocalDatabaseProtocol,
dataSyncService: DataSyncServiceProtocol) {
self.userDefault = userDefault
self.localDatabase = localDatabase
self.dataSyncService = dataSyncService
}
func authorizeHealthKit(completion: @escaping () -> Void) {
//省略
}
func updateCharacteristicIdentifiers() {
//省略
}
public func startObservingDataChanges(queue: DispatchQueue?, isBackgroundTask: Bool, completion: @escaping () -> Void) {
//省略
}
public func getMostRecentHealthKitSample<T>(for sampleType: HKSampleType,
completion: @escaping ([T], Date, Error?) -> Void) where T: HKSample {
//省略
}
private func queryECGSample(ecgSample: HKElectrocardiogram, ecgId: String) {
//省略
}
private func updateEndTime(identifier: String, endDate: Date) {
//省略
}
private func storeDataToDatabase<T>(model: T) where T: HealthKitModelProtocol {
//省略
}
private func storeDataToDatabase<T>(type: String, models: [T]) where T: BaseUploadDataModel {
//省略
}
}
主な機能としては以下の通りです:
- HealthKitデータの読み取りと同期化:
authorizeHealthKit
メソッドにより、ユーザーにHealthKitデータへのアクセス許可を求め、startObservingDataChanges
メソッドにより、ユーザーのデータ変更を監視し、変更があった場合にそれを同期化します。 - 特性識別子の更新:
updateCharacteristicIdentifiers
メソッドは、ユーザーの特性情報(例: 生物学的性別、車椅子の利用状況など)を更新し、アップロードデータに追加します。 - HealthKitデータのクエリと処理:
getMostRecentHealthKitSample
メソッドは、指定されたサンプルタイプに関連する最新のHealthKitデータを取得し、そのデータを処理します。 - データのローカルおよびリモートへの保存:
storeDataToDatabase
メソッドは、データをローカルデータベースに保存し、DataSyncServiceProtocol
を介してデータをリモートサーバーにアップロードします。 - バックグラウンドでのタスク管理: バックグラウンドでのタスク実行に関連する処理も含まれており、
DispatchQueue
を使用して非同期処理を制御します。
healthKitActivityType
で活動タイプの定義
healthKitActivityType
で活動タイプの定義 public static var healthKitActivityType: [HKSampleType] {
var list = [
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!,
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.distanceWalkingRunning)!,
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.pushCount)!,
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.distanceWheelchair)!,
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.activeEnergyBurned)!,
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.basalEnergyBurned)!,
//mobility
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.appleWalkingSteadiness)!,
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.walkingSpeed)!,
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.walkingStepLength)!,
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.walkingAsymmetryPercentage)!,
//heart rate
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRate)!,
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.restingHeartRate)!,
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRateVariabilitySDNN)!,
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.walkingHeartRateAverage)!,
//blood pressure
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.oxygenSaturation)!,
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bloodPressureSystolic)!,
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bloodPressureDiastolic)!,
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.respiratoryRate)!,
HKObjectType.electrocardiogramType()
]
if #available(iOS 16, *) {
list.append(HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.atrialFibrillationBurden)!)
list.append(HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRateRecoveryOneMinute)!)
}
return list
}
healthKitActivityType
は、HealthKitフレームワークで使用されるさまざまな活動タイプを表すHKSampleType
の配列です。この配列に含まれる各HKSampleType
は、特定の健康活動やフィットネスデータを表します。
以下は、healthKitActivityType
で定義される主な活動タイプのいくつかです:
- ステップ数 (
HKQuantityTypeIdentifier.stepCount
) - 歩行およびランニングの距離 (
HKQuantityTypeIdentifier.distanceWalkingRunning
) - プッシュ回数 (
HKQuantityTypeIdentifier.pushCount
) - 車椅子での移動距離 (
HKQuantityTypeIdentifier.distanceWheelchair
) - 消費したアクティブエネルギー量 (
HKQuantityTypeIdentifier.activeEnergyBurned
) - 休息時の心拍数 (
HKQuantityTypeIdentifier.restingHeartRate
) - その他多くの健康活動やフィットネスに関連するデータ
これらの活動タイプは、ユーザーがiPhoneやApple Watchなどのデバイスを使用して行ったさまざまな活動や運動に関するデータを収集し、HealthKitフレームワークを介してアプリケーションに提供します。
HKUnitとは?
HKUnit
は、HealthKitフレームワークで使用される単位を表すクラスです。HealthKitは、ヘルスデータを取得、保存、管理するためのフレームワークであり、さまざまなヘルスデータ(身長、体重、心拍数など)の単位を表すためにHKUnit
が使用されます。
例えば、心拍数の単位は「count/min」(1分あたりのカウント数)であり、これはHKUnit(from: "count/min")
として表現されます。また、体重の単位は「kg」(キログラム)であり、これはHKUnit.gramUnit(with: .kilo)
として表現されます。
HKUnit
クラスは、さまざまな単位のインスタンスを作成するための便利なメソッドも提供しています。これにより、ヘルスデータを取り扱うアプリケーションで正確な単位を指定することができます。
mapHealthKitActivityUnit
の定義
public static var mapHealthKitActivityUnit: [HKSampleType: HKUnit] {
var list = [
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)! : HKUnit.count(),
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.distanceWalkingRunning)! : HKUnit.meter(),
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.pushCount)! : HKUnit.count(),
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.distanceWheelchair)!: HKUnit.meter(),
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.appleWalkingSteadiness)!: HKUnit.percent(),
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.walkingSpeed)!: HKUnit(from: "m/s"),
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.walkingStepLength)!: HKUnit.meter(),
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.walkingAsymmetryPercentage)!: HKUnit.percent(),
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRate)!: HKUnit(from: "count/min"),
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.restingHeartRate)!: HKUnit(from: "count/min"),
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRateVariabilitySDNN)!: HKUnit.minute(),
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.walkingHeartRateAverage)!: HKUnit(from: "count/min"),
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.oxygenSaturation)!: HKUnit.percent(),
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bloodPressureSystolic)!: HKUnit.millimeterOfMercury(),
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bloodPressureDiastolic)!: HKUnit.millimeterOfMercury(),
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.respiratoryRate)!: HKUnit(from: "count/min")
]
if #available(iOS 16, *) {
list[HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.atrialFibrillationBurden)!] = HKUnit.percent()
list[HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRateRecoveryOneMinute)!] = HKUnit(from: "count/min")
}
return list
}
このコードは、HKSampleType
ごとに対応するHKUnit
をマッピングする静的なメソッド mapHealthKitActivityUnit
を定義しています。このメソッドは、特定の健康データのタイプ(例:歩数、心拍数、血圧など)に対して、適切なHKUnit
を関連付けるための辞書を生成します。
具体的には、次のような対応関係が定義されています:
HKQuantityTypeIdentifier.stepCount
には、HKUnit.count()
(個数)が関連付けられています。HKQuantityTypeIdentifier.distanceWalkingRunning
には、HKUnit.meter()
(メートル)が関連付けられています。HKQuantityTypeIdentifier.heartRate
には、HKUnit(from: "count/min")
(1分あたりのカウント数)が関連付けられています。
このように、各健康データのタイプに対して適切な単位が定義され、健康データを正しく取り扱うための基盤が整えられています。また、#available(iOS 16, *)
を使用して、iOS 16以降で利用可能な特定の健康データの追加に対応しています。