Healthkitとは
iOSでは、iOSやサードパーティアプリから ヘルスケア
にいろいろなヘルスケアデータが書き込まれます。
iOSアプリはヘルスケアデータをHealthkit経由で読み書きが可能で、またデータの更新を監視することができます。
それでは直近2年ぐらいで踏み抜いたHealthkit関連のTipsをどうぞ
Healthkitのハマりどころ
1. iPadをサポートしてないアプリでもiPadで機能が動いてないとAppStore申請時にリジェクトされる
原因
- 「ヘルスケア」はiPadに入ってないのでiPadのサポートを切ることが多い
- しかしAppleの人はiPadのiPhone互換モードで動作確認する
解決策
↓のメソッドでヘルスケアが利用可能な端末か識別して制御しておく
class func isHealthDataAvailable() -> Bool
2. AppStoreの申請情報の書き方でリジェクトされる
ヘルスケアデータのデータソースとしてAppleのヘルスケア以外も対応してるアプリで↓のような文章を書くとAppStoreレビューでリジェクトされることがある。
このアプリはFitbitから歩数データを連携できます!
解決策
Appleのヘルスケアも対応していることを併記する
このアプリはAppleのヘルスケアやFitbitから歩数データを連携できます!
3. パーミッション要求しても許可画面が表示されないことがある
↓のメソッドでヘルスケアのパーミッション要求をすると許可画面が表示されるはずが、
func requestAuthorization(toShare typesToShare: Set<HKSampleType>?,
read typesToRead: Set<HKObjectType>?,
completion: @escaping (Bool, Error?) -> Void)
completion に↓のようなErrorが返ってきて表示されない。
Error Domain=com.apple.healthd.SQLite Code=1 "Transaction block failed without an error." UserInfo={NSLocalizedDescription=Transaction block failed without an error.}
原因
- 数年前から開発者フォーラム に投稿されているが明確な原因はわからない
- iPhoneSE第一世代/iOS13.2.1で実際に発生していた
- アプリのアンインストール/再インストールを繰り返しているとまれに発生する
解決策
- 端末を再起動すると発生しなくなった(事象ベースで根本的に解決してませんすいません)
- パーミッション要求のエラーハンドリングでユーザに端末の再起動を促す
4. アクセス許可したあとにタップ操作ができなくなることがある
原因
ヘルスケアのパーミッション要求し、ユーザが許可画面で許可/不許可を設定して画面がクローズした後もHealthkitが表示した透明のViewを持つUIWindowが最前面に残り続けることがある。
解決策
アプリのメインWindowとHealthkitが表示したWindowの前面になるようWindowレベルを設定する。
詳しくはこちらをどうぞ。
5. データの読み出しが不許可になっていることはわからない/データが微妙に取得できない
書き込みのパーミッションは↓で取得できるが、読み出しの許可状態はわからない
func authorizationStatus(for type: HKObjectType) -> HKAuthorizationStatus
理由
- ドキュメント に書かれているとおり、機密性の高い健康情報の漏洩を防ぐためにアプリはユーザーがデータの読み出しを許可したかどうかを判断できないようになっている
- 取得処理を実行した場合はデータがないように見える
- 自身のアプリが書き込んだデータは読み出しが不許可でも取得できる
6. データが取得できない
原因
- 前述のとおり読み出しが拒否されてたら取れない
- 端末がロックされているときは暗号化されているためエラーになる
- 以前、アプリが終了している状態でもヘルスケアデータの更新をフックして処理を実行できる という記事を書いた。こちらは更新があったこと自体は検知できるが、端末がロックされているときはデータ取得がエラーになるため工夫が必要
- WidgetKitなどでも同じ
7. 取得したデータの値が異常なことがある
歩数など1日で歩けないような数値が入ってくることがある
原因①
データを手入力できるアプリを経由してヘルスケアに書き込まれている
解決策①
Appleの端末で自動計測されたデータだけに絞る(サードパーティアプリからヘルスケアに連携されたデータは含まない)
こんな感じで限定することができる
let healthStore = HKHealthStore()
let stepCountType = HKQuantityType.quantityType(forIdentifier: .stepCount)!
let now = Date()
let start = now.addingTimeInterval(-1 * 60 * 60 * 24 * 30)
let end = now
let anchorDate = Calendar.current.startOfDay(for: now)
var intervalComponents = DateComponents()
intervalComponents.day = 1
let datePredicate = HKQuery.predicateForSamples(withStart: start, end: end)
let statisticsCollectionQuery = HKStatisticsCollectionQuery(quantityType: stepCountType,
quantitySamplePredicate: datePredicate,
options: [.cumulativeSum, .separateBySource],
anchorDate: anchorDate,
intervalComponents: intervalComponents)
statisticsCollectionQuery.initialResultsHandler = { query, results, error in
guard let sources = results?.sources().filter({ $0.bundleIdentifier.lowercased().hasPrefix("com.apple.health") }) else {
return
}
let sourcesPredicate = HKQuery.predicateForObjects(from: Set(sources))
let predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [datePredicate, sourcesPredicate])
let statisticsCollectionQuery2 = HKStatisticsCollectionQuery(quantityType: stepCountType,
quantitySamplePredicate: predicate,
options: [.cumulativeSum, .separateBySource],
anchorDate: anchorDate,
intervalComponents: intervalComponents)
statisticsCollectionQuery2.initialResultsHandler = { query, results, error in
results?.statistics().forEach {
print($0.sumQuantity()) // 日次の歩数合計
}
}
healthStore.execute(statisticsCollectionQuery2)
}
healthStore.execute(statisticsCollectionQuery)
※HKStatisticsCollectionQuery
でソースを絞るやり方はもっといい方法があるかもしれません
原因②
ヘルスケアでデータが手入力されている
解決策②
ヘルスケアに手入力されたデータはクエリで除外する
HKSampleQuery
や HKStatisticsQuery
などに↓を追加するとユーザが手入力したデータを除外できる
let predicate = NSPredicate(format: "metadata.%K != YES", HKMetadataKeyWasUserEntered)
8. iCloudバックアップ/iTunesバックアップからの復元時、ヘルスケアからアプリへの読み出し/書き込み許可はリセットされる
- UserDefaultsやKeychainなどのデータやプッシュ通知許可などは復元されるが、ヘルスケアのパーミッションは復元されない
- ユーザが機種変更したときなどヘルスケアのパーミッションだけがリセットされた状態になる
設定アプリ→[ヘルスケア]→[データアクセスとデバイス] で確認するとAPPが消えている(例)
おわり
Appleもすごいヘルスケアに力を入れていて扱えるデータの種類もどんどん増えているので、これからアプリを作ってみたい人のお役に立てば幸いです!
また DeNA 公式 Twitter アカウント @DeNAxTech では色々な勉強会での登壇資料も発信してます。ぜひフォローして下さい!