こんにちは、大阪のお好み焼屋です。お好み焼は最高ですが、Swiftも最高ですね。そんなわけで先日リリースした、お好み焼の栄養成分をヘルスケア(Health.app)へ送るApp、その名もレコノミーに絡めて、HealthKitをSwiftで利用する話です。
HealthKit
iOS8で新たに加わったHealthKit。いまいち盛り上がっている感じもありませんが、とりあえずデータをためておけば後でなにかいいことがあるかも・・・というわけで、iOS9で加えられたHKCorrelationTypeIdentifierFood
をつかって複数の栄養素をまとめて「メニュー単品」としてHealth.appへ送ることにします。ここではサンプルとしてうち自慢のイカ玉をつかいます。
サンプルコードと参考スクリーンショット
主な登場Class
HealthKit | |
---|---|
HKUnit | 単位 |
HKQuantity | 量 |
HKQuantityType | 量のタイプ |
HKQuantitySample | モノ |
「モノ」というのがよくわからないですが、とりあえずの目標がこれだと思ってください。
HKUnit, HKQuantity
順番が前後しますが、まずはHKQunatity
の初期化メソッドです
init(unit unit: HKUnit!, doubleValue value: Double)
Unitは単位で、Quantityは量のことですね。unit
単位にdoubleValue
の値を与えてやることで量になります。100.0という数(Double
)に単位グラム(HKUnit
)を与えてやることで、「100グラム」という量になるわけです。
unitの初期化はいろいろなやり方が用意されています
HKUnit.percentUnit()
HKUnit(fromString: "cm")
HKUnit.gramUnitWithMetricPrefix(.Kilo)
ひとつめはいわゆるConvenience Constructor的なやつで、ここでは「%」ですが、他にも結構な数が用意されています。
2つめは単位を文字列で表す方法(ここではセンチメートル)。”m/s^2”(加速度|$m/s^2$)なんかも可能。
3つめは読んだ通り「メートル法のグラム単位をキロで」。これでキログラムになります。
let kcalUnit = HKUnit.kilocalorieUnit()
let quantity = HKQuantity(unit: kcalUnit, doubleValue: 347)
HKQuantityType, HKQuantitySample
次に量のタイプです。カロリーと一口にいっても、摂取したカロリーなのか(HKQuantityTypeIdentifierDietaryEnergyConsumed
)、運動で消費したカロリーなのか(HKQuantityTypeIdentifierActiveEnergyBurned
)、はたまた基礎エネルギーの消費なのか(HKQuantityTypeIdentifierBasalEnergyBurned
)を、HKQuantityType
でしっかり指定してやります。
これでようやく必要な要素がそろってHKQuantitySampleのインスタンス化ができるようになりました。
let type = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierDietaryEnergyConsumed)!
let date = NSDate()
let ikatamaEnergySample = HKQuantitySample(type: type, quantity: quantity, startDate: date, endDate: date)
これでイカ玉のカロリーが完成です。あとは同じ手順で他の必要な栄養素を単位に気をつけつつインスタンス化していきます。
たとえばプロテイン(蛋白質)はこんな具合
let gramUnit = HKUnit.gramUnit()
let proteinQuantity = HKQuantity(unit: gramUnit, doubleValue: 18.9)
let proteinType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierDietaryProtein)!
let ikatamaProteinSample = HKQuantitySample(type: proteinType, quantity: proteinQuantity, startDate: date, endDate: date)
HKCorrelation
コードを見ていただければ一目瞭然だとおもいます。
var itemSet = Set<HKQuantitySample>()
itemSet.insert(ikatamaEnergySample)
//// 必要な栄養のサンプルを`insert(_)`していく
let foodType = HKCorrelationType.correlationTypeForIdentifier(HKCorrelationTypeIdentifierFood)!
let ikatama = HKCorrelation(type: foodType, startDate: date, endDate: date, objects: itemSet, metadata: metadata)
HKHealthStore
あとはストアのアベイラビリティをチェックして、ストアへのアクセスをリクエストしてやります。フレームワークが面倒をみてくれます。
guard HKHealthStore.isHealthDataAvailable() else { return }
let healthStore = HKHealthStore()
let typeSet: Set<HKSampleType> = [energyType, proteinType]
healthStore.requestAuthorizationToShareTypes(typeSet, readTypes: nil) { success, error -> Void in
// if request is approved
healthStore.saveObject(ikatama) { success, error in
if success { print("DONE!!") }
}
}
無事送れています。
最後に
あわてて書いたのであまりSwiftっぽい話はできませんでしたが、レコノミー内ではenum
を使いまくったりして、とても楽しく書くことができています。また機会があればenum+protocolの話も書ければと思っています。ありがとうございました。