[iOS 8] HealthKitを実装する(3) HealthStoreからデータを取得する

2014.09.18

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

HealthStoreからデータを取得する実装例

アプリケーションがHealthStoreからデータを取得する場合、永続化する場合と同様にユーザーの許可が必要です。

以下はHealthStoreに永続化された体温を全件取得するサンプルです。

/**
HealthStoreから引数に渡されたデータ型に一致する健康情報を全件取得します。

:param: unit       健康情報の単位型
:param: type       取得したいデータ型
:param: completion 取得完了時に実行される処理
*/
func findAllHealthValueWithUnit(unit: HKUnit!, type: HKQuantityType!, completion: ((query: HKSampleQuery!, responseObj: [AnyObject]!, error: NSError!) -> Void)) {
    let healthStore = HKHealthStore()
    
    // HealthStoreのデータを全件取得するHKSampleQueryを返却します。
    let findAllQuery : () -> HKSampleQuery = {
        return HKSampleQuery(sampleType: type, predicate: nil, limit: 0, sortDescriptors: nil, resultsHandler: completion)
    }
    
    let types: NSSet! = NSSet(object: type)
    
    let authStatus:HKAuthorizationStatus = healthStore.authorizationStatusForType(type)
    
    if authStatus == .SharingAuthorized {
        healthStore.executeQuery(findAllQuery())
    } else {
        
        // 体温型のデータをHealthStoreから取得するために、ユーザーへ許可を求めます。
        // 許可されたデータのみ、アプリケーションからHealthStoreへ読み込みする権限が与えられます。
        // ヘルスケアの[ソース]タブ画面がモーダルで表示されます。
        // 第1引数に指定したNSSet!型のshareTypesの書き込み許可を求めます。
        // 第2引数に指定したNSSet!型のreadTypesの読み込み許可を求めます。
        
        healthStore.requestAuthorizationToShareTypes(types, readTypes: types) {
            success, error in
            
            if error != nil {
                NSLog(error.description);
                return
            }
            
            if success {
                NSLog("取得可能");
                // 引数に指定されたクエリーを実行します
                healthStore.executeQuery(findAllQuery())
            }
        }
    }
}

func findAllBodyTemperature() {
    // 体温の単位を生成します。単位は℃(摂氏)です。
    let btUnit: HKUnit! = HKUnit.degreeCelsiusUnit()
    // 体温情報の型を生成します。
    let btType: HKQuantityType! = HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBodyTemperature)
    
    // 取得処理完了時に非同期で呼び出されます。
    findAllHealthValueWithUnit(btUnit, type: btType , {
        query, responseObj, error in
        
        if error != nil {
            NSLog(error.description)
            return
        }
        
        // 取得した結果がresponseObjに格納されています。
        // アプリケーションで使用する場合、[AnyObject]!型のresponseObjを必要な型にキャストする必要があります。
        NSLog("resultObj : \(responseObj)")
        
        let btUnit: HKUnit = HKUnit.degreeCelsiusUnit()
        
        var btResults: [Double!] = []
        
        // HealthStoreで使用していた型から体温の値へと復元します。
        for bodyTemperature: HKQuantitySample in responseObj as [HKQuantitySample] {
            // 値を取得します。
            let btQuantity: HKQuantity! = bodyTemperature.quantity
            let btResult: Double = btQuantity.doubleValueForUnit(btUnit)
            btResults.append(btResult);
        }
        NSLog("values : \(btResults)")
    })
}

同じく実行される順に、各処理を解説します。


findAllBodyTemperature()

体温データの情報を元にfindAllHealthValueWithUnit(unit: HKUnit!, type: HKQuantityType!, completion: ((query: HKSampleQuery!, responseObj: [AnyObject]!, error: NSError!) -> Void))を呼び出しています。取得したいデータによってこちらのメソッドを変えると良いでしょう。

findAllHealthValueWithUnit(unit: HKUnit!, type: HKQuantityType!, completion: ((query: HKSampleQuery!, responseObj: [AnyObject]!, error: NSError!) -> Void))

一連の取得処理を実行します。

findAllQuery() -> HKSampleQuery

HealthStoreへデータを問い合わせるためのクエリーを返却します。

HKSampleQueryのコンストラクター引数を変更することによって、取得するデータの指定・特定条件の絞り込み・取得件数の制御・ソートが行えます。

今回は絞り込み条件なし、取得件数は全件(limit0は全件取得)、ソート条件はなしで実行しています。

クエリーの実行完了時にcompletionメソッドが実行されます。

completion(query: HKSampleQuery!, responseObj: [AnyObject]!, error: NSError!)

クエリーの結果を取得できます。

取得した結果は第2引数に[AnyObject]!型で渡されます。

こちらの配列から任意の型へキャストすることによって、アプリケーションで使用することが可能です。

今回はHKQuantitySampleの配列から、体温型を指定してDouble型へキャストしています。

脚注