共有機能(UIActivityViewController)を実装したあと、アプリ内の記録と歩数などのヘルスデータを組み合わせて表示したくなり、HealthKitでの連携に挑戦しました。
1. 読み取りと書き込みで許可の仕組みが違うと知らなかった
最初、他の権限(カメラや位置情報など)と同じように、一度許可を得れば読み書き両方できるものだと思い込んでいました。
let typesToRead: Set = [HKQuantityType(.stepCount)]
let typesToShare: Set = [HKQuantityType(.stepCount)]
healthStore.requestAuthorization(toShare: typesToShare, read: typesToRead) { success, error in
// 権限リクエスト結果
}
HealthKitでは「読み取り」と「書き込み」を別々に許可申請する仕組みになっており、しかも読み取りが拒否されたかどうかをアプリ側から判別できないという独特の制限があります。許可されたのか拒否されたのかを前提にした分岐は書けず、常に「データが取得できない可能性がある」前提で実装する必要がありました。
2. シミュレーターでは正しく動作確認できなかった
実装した歩数取得処理をシミュレーターで試したところ、常に空のデータしか返ってこず、実装が間違っているのかと悩みました。
シミュレーターにはヘルスケアアプリ自体が用意されておらず、実際の歩数データを模擬する手段が限られています。実機で自分のiPhoneのヘルスケアデータを使って確認したところ、正しく取得できることが分かりました。位置情報や生体認証のときと同様、実機前提の機能だと再確認しました。
3. Info.plistの権限説明文を1つ書けば十分だと思っていた
NSHealthShareUsageDescriptionだけをInfo.plistに追加して満足していたのですが、書き込み権限も使う設計にしたところ、審査時に別のキーが必要だと気づきました。
NSHealthShareUsageDescription: 読み取り権限の説明文
NSHealthUpdateUsageDescription: 書き込み権限の説明文
読み取りと書き込みでそれぞれ専用の説明文キーが必要で、片方だけでは不十分でした。使う権限の種類に応じて両方を用意しておく必要があると学びました。
4. データの単位変換で数値がおかしくなった
歩数以外に消費カロリーも取得しようとしたところ、表示される数値が明らかにおかしいことに気づきました。
let calories = sample.quantity.doubleValue(for: .kilocalorie())
取得したHKQuantityは、明示的に単位を指定して数値に変換する必要があり、単位の指定を誤っていたのが原因でした。HealthKitのデータは内部的に単位を保持しているため、取り出す際に必ず正しい単位(kilocalorieやcountなど)を指定する必要があると理解しました。
まとめ
- HealthKitは「読み取り」と「書き込み」の許可が別々。読み取りが拒否されたかはアプリ側から判別できない前提で設計する
- ヘルスデータの動作確認はシミュレーターでは困難。実機の実データで確認する
- 読み取り・書き込みそれぞれに専用のInfo.plistキーが必要
- データを数値化する際は、必ず正しい単位を明示的に指定する
センシティブな個人情報を扱う分、プライバシーへの配慮が仕組みレベルで組み込まれていることを実感した実装でした。
次は、インタラクティブウィジェットを実装してつまずいた話をまとめます。
本記事は生成AI(Claude)を活用して執筆・編集しています。内容は実体験に基づき、執筆者本人が確認・監修しています。


コメント