一週間分の歩数を取得する


モーションコプロセッサが搭載されたiPhone 5s以降の端末では一週間分の歩数を取得することができます。

はじめに、CoreMotion.frameworkを追加します。

CMPedometer.isStepCountingAvailable()で歩数が取得できるか判定します。

if(!CMPedometer.isStepCountingAvailable()) {
  // 取得できないとき
}

取得開始と取得終了のNSDateを指定します。

let pedometer:CMPedometer = CMPedometer()

pedometer.queryPedometerDataFromDate(from, toDate: to, withHandler: {(pedometerData:CMPedometerData!, error:NSError!) in

})

pedometerDataに歩数に関する情報が格納され、次のような情報にアクセスできます。

pedometerData.numberOfSteps // 歩数
pedometerData.distance // 距離
pedometerData.floorsAscended // 上った回数
pedometerData.floorsDescended // 下った回数

1週間分の歩数を日別に取得するために今日を基準にして、1日前、2日前、3日前と取得していきます。

/**
歩数計に関する一週間分の情報を返します。

:returns: 歩数計に関する情報
*/
func pedometerQuery() -> NSMutableArray {
    var result = NSMutableArray()

    let pedometer:CMPedometer = CMPedometer()
    if(!CMPedometer.isStepCountingAvailable()) {
        return result
    }

    let now:NSDate = NSDate()
    let formatter:NSDateFormatter = NSDateFormatter()
    formatter.dateFormat = "yyyy-MM-dd"
    var from:NSDate = self.stringToDate(formatter.stringFromDate(now), isStart: true)
    var to:NSDate = self.stringToDate(formatter.stringFromDate(now), isStart: false)

    for i in 0...6 {
        let semaphore:dispatch_semaphore_t = dispatch_semaphore_create(0)

        pedometer.queryPedometerDataFromDate(from, toDate: to, withHandler: {(pedometerData:CMPedometerData!, error:NSError!) in
            result[i] = [
                "steps": pedometerData.numberOfSteps,
                "distance": pedometerData.distance,
                "floorsAscended": pedometerData.floorsAscended,
                "floorsDescended": pedometerData.floorsDescended,
                "startDate": pedometerData.startDate,
                "endDate": pedometerData.endDate
            ]

            dispatch_semaphore_signal(semaphore)
        })
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)

        from = self.dateByAddingDay(from, day: -1)
        to = self.dateByAddingDay(to, day: -1)
    }

    return result
}

/**
指定した日付に時分秒を追加して新しいNSDateを返します。

:param: date もとのNSDate
:param: isStart trueのとき00:00:00、falseのとき23:59:59を追加します
:returns: 新しいNSDate
*/
private func stringToDate(date: String, isStart: Bool) -> NSDate {
    let timestamp = (isStart) ? date + " 00:00:00" : date + " 23:59:59"
    let formatter:NSDateFormatter = NSDateFormatter()
    formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
    return formatter.dateFromString(timestamp)!
}

/**
指定した日数を加減した新しいNSDateを返します。

:param: date もとのNSDate
:param: day 加減する日数
:returns: 新しいNSDate
*/
private func dateByAddingDay(date: NSDate, day: Int) -> NSDate {
    let calendar:NSCalendar = NSCalendar.currentCalendar()
    let components:NSDateComponents = NSDateComponents()
    components.day = day
    return calendar.dateByAddingComponents(components, toDate: date, options: NSCalendarOptions.allZeros)!
}