0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Swift: HealthKitに体温データを入力する。できるだけ公式ドキュメントだけを見て。

Last updated at Posted at 2021-10-14

まずは公式ドキュメントをちゃんと読む人間になろうと思いたち、Apple公式ドキュメントだけを元にHealthKitにアクセスを試みました。

環境

  • XCode Version 13.0
  • iOS target 14.0

参考(公式)

プロジェクト設定

HealthKitの有効化(プロジェクト設定の「Signing & Capabilities」にHealthKitを追加

image.png

アクセス要求用のメッセージ定義

image.png

今回は体温データの入力のみなのでPrivacy - Health Update Usage Description
アプリが読み出しする場合はPrivacy - Health Share Usage Descriptionが必要になります

参考: Protecting User Privacy (developer.apple.com)

これらのDescriptionは13文字以上必要なようです。これに関しては調査力が足りず、StackOverflowのお世話になりました。

https://stackoverflow.com/questions/37863093/exception-nsinvalidargumentexception-nshealthupdateusagedescritption

コード

今回は1つのクラス内でHealthKitへの参照を完結させます

setup()

HKHealthStoreはドキュメントによれば、無闇に生成せず保持し続けるのがいいようです。

You need only a single HealthKit store per app. These are long-lived objects; you create the store once, and keep a reference for later use.

Setting Up HealthKit (developer.apple.com)

エラーチェックで呼び出し側の処理を変えることなども考慮し、setup()メソッドでStoreの生成を行います。(エラーチェックが不要であればinit()内で生成してました)

postBodyTemperature()

以下の順番で処理を行います

  • 体温データに関するアクセス許可取得
  • アクセス許可状態の確認
  • 体温データの保存

出来上がったClass

import Foundation
import HealthKit

enum BodyTemperatureUnit{
    /// 摂氏
    case degreeCelsius
    /// 華氏
    case degreeFahrenheit
}
class HealthCareRepository{
    let allTypes = Set([HKObjectType.quantityType(forIdentifier: .bodyTemperature)!])
    /// HKHealthStoreはアプリケーションあたり1インスタンス。1回生成したらそれを使い続ける必要あり
    var store:HKHealthStore? = nil
    
    func setup() -> Bool{
        /// ipadではヘルスケア使えない
        /// https://developer.apple.com/documentation/healthkit/setting_up_healthkit
        /// Ensure HealthKit’s Availability
        if (HKHealthStore.isHealthDataAvailable() == false){
            // ヘルスデータが無効状態
            return false
        }
        
        /// ヘルスケア機能があり、有効である場合生成する
        self.store = HKHealthStore()
        return true
    }

    func postBodyTemperature(_ value:Double, unit:BodyTemperatureUnit, completion:@escaping (Bool, Error?) -> Void) -> Void{
        
        /// https://developer.apple.com/documentation/healthkit/authorizing_access_to_health_data
        /// Request Permission from the User
        /// toShare: Write要求
        /// read: Read要求
        self.store!.requestAuthorization(toShare: allTypes, read: nil){ (success, error) in
            if !success{
                completion(success, error)
                return
            }
            
            /// https://developer.apple.com/documentation/healthkit/authorizing_access_to_health_data
            /// Check for Authorization Before Saving Data
            let status = self.store!.authorizationStatus(for: .quantityType(forIdentifier: .bodyTemperature)!)
            switch status{
            case .notDetermined:
                // "If you have not yet requested permission"
                // ここに入ることはないはず
                print("Not determined")
                completion(false, HKError(HKError.errorAuthorizationNotDetermined))
                return
            case .sharingDenied:// If the user has denied permission
                // ユーザーが許可しなかった場合
                print("Sharing Denied")
                completion(false, HKError(HKError.errorAuthorizationDenied))
                break
            case .sharingAuthorized:
                // ユーザーが許可した場合
                print("Sharing Authorized")
                break
            @unknown default:
                print("Unknown status.")
                break
            }
            
            // Datetime
            let now = Date()
            // 摂氏 or 華氏
            let hkUnit:HKUnit
            switch unit {
            case .degreeCelsius:
                hkUnit = .degreeCelsius()
            case .degreeFahrenheit:
                hkUnit = .degreeFahrenheit()
            }
            
            let quantity = HKQuantity(unit: hkUnit, doubleValue: value)
            let obj = HKQuantitySample(type: .quantityType(forIdentifier: .bodyTemperature)!, quantity: quantity, start: now, end: now)
            self.store!.save(obj, withCompletion: completion)
        }
    }
}

結果

適当なUI作って上記クラスを試した結果、シミュレータ上ではありますが無事に体温データをヘルスケアに登録することができました。大抵のことは公式Documentに書いてあることも実感できました。次回はUI予定です。

image.png

0
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?