ios - hkworkout totalenergyburned doesn't correlate with HKQuantityTypeIdentifierActiveEnergyBurned -
this more of data structure question programming syntax question. data structure of health app of black box.
i want query hkhealthstore , create both daily summary of items including, activeenergyburned, , summary of workouts including totalenergyburned.
i have code (below) retrieves information. number daily total less day's workout! sure code not problem, because exact same numbers show in apple health app. example:
yesterday's workout: app workout.totalenergyburned = 905 kcal sum of yesterday's activeenergyburned 655 kcal health app shows exact same numbers both.
if activeenergyburned, doesn't include workouts, include? didn't have 655 of activeenergyburned. doesn't seem possible me activeenergyburned wouldn't include workouts!
//to sum of day's activecaloriesburned: func getactivecalories(startdate:nsdate, enddate:nsdate){ let sampletype = hksampletype.quantitytypeforidentifier(hkquantitytypeidentifieractiveenergyburned) let hkunit = hkunit.kilocalorieunit() getsumstatsfor(sampletype, hkunit: hkunit, startdate: startdate, enddate: enddate) { (hdobject, result) -> void in hdobject.activecalories = result } } func gettotalsfordatatype(quantitiytype:hkquantitytype, startdate:nsdate, enddate:nsdate, completion:(hkstatisticscollection!, nserror!) -> void){ println("gettotalsfordatatype start: \(startdate) end: \(enddate)") let daystart = nscalendar.currentcalendar().startofdayfordate(startdate) let addday = nscalendar.currentcalendar().datebyaddingunit(.calendarunitday, value: 1, todate: enddate, options:nil) let dayend = nscalendar.currentcalendar().startofdayfordate(addday!) //add 1 day let interval = nsdatecomponents() interval.day = 1 let predicate = hkquery.predicateforsampleswithstartdate(startdate, enddate: enddate, options: hkqueryoptions.none) let newquery = hkstatisticscollectionquery(quantitytype: quantitiytype, quantitysamplepredicate: predicate, options: hkstatisticsoptions.cumulativesum, anchordate: daystart, intervalcomponents: interval) newquery.initialresultshandler = { query, results, error in if error != nil { println("*** error occurred while calculating statistics: \(error.localizeddescription) ***") completion(nil, error) }else{ completion(results,error) } } self.healthkitstore.executequery(newquery) } //to workout totalcalories burned func readworkouts(completion: (([anyobject]!, nserror!) ->void)!){ let sortdescriptor = nssortdescriptor(key: hksamplesortidentifierstartdate, ascending: false) let samplequery = hksamplequery(sampletype: hkworkouttype.workouttype(), predicate: nil, limit: 0, sortdescriptors: [sortdescriptor]) { (samplequery, results, error) -> void in if let queryerror = error { println( "there error while reading samples: \(queryerror.localizeddescription)") } completion(results,error) } healthkitstore.executequery(samplequery) }
this due bug how healthkit workout api designed. current api it's possible 3rd party apps create hkworkouts totalenergyburned greater 0, no associated hksamples of hkquantitytypeidentifieractiveenergyburned type created sum totalenergyburned. example, 3rd party app feeds workout data healthkit this:
hkhealthstore *healthstore = [hkhealthstore new]; hkworkout *workout = [hkworkout workoutwithactivitytype:hkworkoutactivitytypeplay startdate:[nsdate date] enddate:[nsdate date] duration:100.0 totalenergyburned:[hkquantity quantitywithunit:[hkunit kilocalorieunit] doublevalue:445] totaldistance:[hkquantity quantitywithunit:[hkunit meterunit] doublevalue:1000] metadata:nil]; [healthstore saveobject:workout withcompletion:nil]; note hksamples created of type hkquantitytypeidentifieractiveenergyburned. when sum active energy burned day , compare workout's total energy burned 0 kcal vs 445 kcal. 3rd party app after creating workout:
nsarray *workoutsamples = @[[hkquantitysample quantitysamplewithtype:hkquantitytypeidentifieractiveenergyburned quantity:[hkquantity quantitywithunit:[hkunit kilocalorieunit] doublevalue:workout.totalenergyburned] startdate:workout.startdate enddate:workout.enddate]]; [healthstore addsamples:workoutsamples toworkout:workout completion:nil]; that way there's @ least active energy burned sample. you'll 445 kcal vs 445 kcal.
in tests 3rd party apps, i've found add active energy burned samples, some, nike running, not.
a hacky workaround pull out of active energy samples workout (you'll have use startdate , enddate because predicateforobjectsfromworkout has similar issues noted above), if there aren't samples, assume source did not create active energy samples workout , add workout's totalenergyburned active energy burned sum day.
Comments
Post a Comment