この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
歩数計機能
iOS 8 の Core Motion フレームワークに CMPedometer という歩数関連のデータを取得することができる API が追加されました。このクラスを使うと歩数/走行距離/昇り降りしたフロアの数などを計測できたり、過去に遡ってデータを参照できたりします。
なお、iOS 7 で追加された CMStepCounter がありますが、これの機能増強版と言えます。CMStepCounter は Deprecated になりました。短命でしたね。。
NS_CLASS_DEPRECATED_IOS(7_0,8_0,"Use CMPedometer instead")
@interface CMStepCounter : NSObject
この API は iPhone 5s に搭載されているモーション・コプロセッサー「M7」以降を利用して歩数を計測するので、電池消費量がかなり少ないです。
CMPedometer を使ってみよう
ということで早速使ってみましょう。まずプロジェクトを作成し Core Motion フレームワークを追加します。
モニタリング
あとはもう実装だけです。まずはモニタリングを行ってみましょう。
// メンバー変数でないと動作しないので注意
let pedometer = CMPedometer()
func startStepCounting() {
// CMPedometerが利用できるか確認
if CMPedometer.isStepCountingAvailable() {
// 計測開始
pedometer.startPedometerUpdatesFromDate(NSDate(), withHandler: {
[unowned self] data, error in
dispatch_async(dispatch_get_main_queue(), {
println("update")
if error != nil {
// エラー
self.label.text = "エラー : \(error)"
println("エラー : \(error)")
} else {
let lengthFormatter = NSLengthFormatter()
// 歩数
let steps = data.numberOfSteps
// 距離
let distance = data.distance.doubleValue
// 速さ
let time = data.endDate.timeIntervalSinceDate(data.startDate)
let speed = distance / time
// 上った回数
let floorsAscended = data.floorsAscended
// 降りた回数
let floorsDescended = data.floorsDescended
// 結果をラベルに出力
self.label.text = "Steps: \(steps)"
+ "\n\nDistance : \(lengthFormatter.stringFromMeters(distance))"
+ "\n\nSpeed : \(lengthFormatter.stringFromMeters(speed)) / s"
+ "\n\nfloorsAscended : \(floorsAscended)"
+ "\n\nfloorsDescended : \(floorsDescended)"
}
})
})
}
}
まずはじめに CMPedometer#isStepCountingAvailable を呼びます。歩数測定ができるデバイス (= M7) のときに true が返ります。測定可能な場合のみ処理を行うようにしましょう。
次に CMPedometer インスタンスを生成し、CMPedometer#startPedometerUpdatesFromDate:withHandler を呼びます。
第一引数は、今までのデータを取得できるように NSDate が指定できるようになっています。メソッドのコール時から計測したい場合は NSDate を生成して渡します。第二引数にはハンドラを渡します。データは CMPedometerData オブジェクトとして渡されます。新しいデータが追加されると、ハンドラがバックグラウンドで繰り返し呼び出されます。別スレッドで呼ばれるので、この中で View の更新などを行いたい場合はメインスレッドで処理しましょう。
実行します。Core Motion フレームワークの API を利用するにはユーザーのプライバシー許可が必要になるため、初回実行時は次のようなダイアログが表示されます。
許可すると、歩数や距離、速さが取得できます。
データの参照
次に過去のデータを参照してみましょう。
func showHistory() {
// CMPedometerが利用できるか確認
if CMPedometer.isStepCountingAvailable() {
// この日から
let fromDate = NSDate(timeIntervalSinceNow: -60 * 60 * 24 * 7)
// この日まで
let toDate = NSDate()
pedometer.queryPedometerDataFromDate(fromDate, toDate: toDate, withHandler: {
[unowned self] data, error in
dispatch_async(dispatch_get_main_queue(), {
println("update")
if error != nil {
// エラー
self.label.text = "エラー : \(error)"
println("エラー : \(error)")
} else {
let lengthFormatter = NSLengthFormatter()
// 歩数
let steps = data.numberOfSteps
// 距離
let distance = data.distance.doubleValue
// 速さ
let time = data.endDate.timeIntervalSinceDate(data.startDate)
let speed = distance / time
// 上った回数
let floorsAscended = data.floorsAscended
// 降りた回数
let floorsDescended = data.floorsDescended
// 結果をラベルに出力
self.label.text = "Steps: \(steps)"
+ "\n\nDistance : \(lengthFormatter.stringFromMeters(distance))"
+ "\n\nSpeed : \(lengthFormatter.stringFromMeters(speed)) / s"
+ "\n\nfloorsAscended : \(floorsAscended)"
+ "\n\nfloorsDescended : \(floorsDescended)"
}
})
})
}
}
過去のデータを取得するには CMPedometer#queryPedometerDataFromDate:toDate:withHandler を呼びます。第一引数、第二引数には取得したい期間を指定し、第三引数には取得結果のコールバックのハンドラを渡します。取得できた場合、モニタリング時と同様 CMPedometerData オブジェクトとして取得できます。
実行すると次のように、期間内の歩数や距離などが取得できます。
まとめ
歩数計機能は CMStepCounter から更に機能が上がっています。歩数などの健康に関する情報は HealthKit でも扱えるようになったので、ユーザーにより身近な存在になったと言えるでしょう。ぜひアプリで活用したいですね。