Calories and Distance data from query

I am working on an exercise app for the watchos 2 and creating streaming queries to retrieve the data for Heartrate, Distance (HKQuantityTypeIdentifierDistanceWalkingRunning) and Calories (HKQuantityTypeIdentifierActiveEnergyBurned) during the workout session by using the following model:


private func createCaloriesBurnedStreamingQuery(workoutStartDate: NSDate) -> HKQuery? {

guard let quantityType = HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierActiveEnergyBurned) else { return nil }

let caloriesQuery = HKAnchoredObjectQuery(type: quantityType, predicate: nil, anchor: anchor, limit: Int(HKObjectQueryNoLimit)) { (query, sampleObjects, deletedObjects, newAnchor, error) -> Void in

guard let newAnchor = newAnchor else {return}

self.anchorCalories = newAnchor

self.updateCalories(sampleObjects)

}

caloriesQuery.updateHandler = {(query, samples, deleteObjects, newAnchor, error) -> Void in

self.anchorCalories = newAnchor!

self.updateCalories(samples)

}

return caloriesQuery

}


The Heartrate data is coming right, however both calories and distance data seems to be coming in a non cumulative form with a very inconsistant values. In the middle of the workout I was getting 300-400 calories and by the end of the workout I got 14-18 cals.


Is there anything I need to do differently here?


Thanks... Alex

Accepted Reply

OK, I went ahead and watched the https://developer.apple.com/videos/wwdc/2015/?id=203

session at WWDC where they explain how to do this. The to get the calories and distance during workout is to use a predicate for the query with your start date. Something like this:


let predicate = HKQuery.predicateForSamplesWithStartDate(workoutStartDate, endDate: nil, options: .None)


let activeEnergyQuery = HKAnchoredObjectQuery(type: self.activeEnergyType, predicate: predicate, anchor: nil, limit: Int(HKObjectQueryNoLimit)) { (query, samples, deletedObjects, newAncor, error) -> Void in

if let activeEnergySamples = samples as? [HKQuantitySample] {

sampleHandler(activeEnergySamples)

}

}

activeEnergyQuery.updateHandler = { (query, samples, deletedObjects, anchor, error) -> Void in

if let activeEnergySamples = samples as? [HKQuantitySample] {

sampleHandler(activeEnergySamples)

}

}


The other thing is that the samples that you received need to be summed:


extension HKQuantity {

func addQuantitiesFromSamples(samples : [HKQuantitySample], unit: HKUnit) -> HKQuantity {

var currentValue = doubleValueForUnit(unit)

for sample in samples {

let value = sample.quantity.doubleValueForUnit(unit)

currentValue += value

}

let result = HKQuantity(unit: unit, doubleValue: currentValue)

return result

}

}


- Alex

Replies

OK, I went ahead and watched the https://developer.apple.com/videos/wwdc/2015/?id=203

session at WWDC where they explain how to do this. The to get the calories and distance during workout is to use a predicate for the query with your start date. Something like this:


let predicate = HKQuery.predicateForSamplesWithStartDate(workoutStartDate, endDate: nil, options: .None)


let activeEnergyQuery = HKAnchoredObjectQuery(type: self.activeEnergyType, predicate: predicate, anchor: nil, limit: Int(HKObjectQueryNoLimit)) { (query, samples, deletedObjects, newAncor, error) -> Void in

if let activeEnergySamples = samples as? [HKQuantitySample] {

sampleHandler(activeEnergySamples)

}

}

activeEnergyQuery.updateHandler = { (query, samples, deletedObjects, anchor, error) -> Void in

if let activeEnergySamples = samples as? [HKQuantitySample] {

sampleHandler(activeEnergySamples)

}

}


The other thing is that the samples that you received need to be summed:


extension HKQuantity {

func addQuantitiesFromSamples(samples : [HKQuantitySample], unit: HKUnit) -> HKQuantity {

var currentValue = doubleValueForUnit(unit)

for sample in samples {

let value = sample.quantity.doubleValueForUnit(unit)

currentValue += value

}

let result = HKQuantity(unit: unit, doubleValue: currentValue)

return result

}

}


- Alex