Reputation: 1999
I'm learning Swift and HealthKit right now and am a bit stuck at retreiving data.
I've already successfully queried my dietaryCaloriesConsumed
for the last 30 days which is being printed to the console.
When I try to do the same with weight data I get no output. Although I'm able to get weight data from a specific date by counting the date backwards and using only the first sample.
My code right now:
func getWeightData2(forDay days: Int, completion: @escaping ((_ weight: Double?, _ date: Date?) -> Void)) {
// Getting quantityType as stepCount
guard let weight = HKObjectType.quantityType(forIdentifier: .bodyMass) else {
print("*** Unable to create a step count type ***")
return
}
let now = Date()
let startDate = Calendar.current.date(byAdding: DateComponents(day: -days), to: now)!
var interval = DateComponents()
interval.day = 1
var anchorComponents = Calendar.current.dateComponents([.day, .month, .year], from: now)
anchorComponents.hour = 0
let anchorDate = Calendar.current.date(from: anchorComponents)!
let query = HKStatisticsCollectionQuery(quantityType: weight,
quantitySamplePredicate: nil,
options: [.mostRecent],
anchorDate: anchorDate,
intervalComponents: interval)
query.initialResultsHandler = { _, results, error in
guard let results = results else {
print("ERROR")
return
}
results.enumerateStatistics(from: startDate, to: now) { statistics, _ in
if let sum = statistics.sumQuantity() {
let weight = Int(sum.doubleValue(for: HKUnit.gramUnit(with: .kilo)).roundToDecimal(2))
print("Weight Tracked: \(weight), on date: \(statistics.endDate)")
// completion(calories, statistics.endDate)
return
}
}
completion(nil, nil)
}
healthStore.execute(query)
}
With this I don't get any output.
With slight changes for dietaryCaloriesConsumed
I get 30 days worth of calories, summed up for each day (with option cumulativeSum
)
What acutally does work is retreiving data for a specific day like this:
func getWeightData(forDay days: Int) {
let quantityType: HKQuantityType = HKQuantityType.quantityType(forIdentifier: .bodyMass)!
// fetch last 30 days
let startDate = Date.init(timeIntervalSinceNow: TimeInterval(-days*24*60*60))
let endDate = Date()
let predicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate)
let sampleQuery = HKSampleQuery.init(sampleType: quantityType, predicate: predicate, limit: HKObjectQueryNoLimit, sortDescriptors: nil) { (query, samples, error) in
DispatchQueue.main.async {
guard let samples = samples else { return }
let mostRecentSample = samples.first as? HKQuantitySample
let bodyMass = mostRecentSample?.quantity.doubleValue(for: HKUnit.gramUnit(with: .kilo)).roundToDecimal(2)
print("Weight tracked: \(bodyMass) on date: \(endDate)")
}
}
healthStore.execute(sampleQuery)
}
From my ViewController I call those functions like this:
profileStore.getTotalCalories(forDay: 30) {_,_ in
}
and
profileStore.getWeightData(forDay: 30)
This works, but I'm sure there is much room for approval.
Any ideas what I'm doing wrong with my first code?
What is the best way to get n days worth of dietaryCaloriesConsumed
or bodyMass
for further processing?
Thanks a lot :)
Upvotes: 1
Views: 1716
Reputation: 1999
I just solved my own issue:
func getWeightData(forDay days: Int, completion: @escaping ((_ weight: Double?, _ date: Date?) -> Void)) {
// Getting quantityType as stepCount
guard let bodyMassType = HKObjectType.quantityType(forIdentifier: .bodyMass) else {
print("*** Unable to create a bodyMass type ***")
return
}
let now = Date()
let startDate = Calendar.current.date(byAdding: DateComponents(day: -days), to: now)!
var interval = DateComponents()
interval.day = 1
var anchorComponents = Calendar.current.dateComponents([.day, .month, .year], from: now)
anchorComponents.hour = 0
let anchorDate = Calendar.current.date(from: anchorComponents)!
// Note to myself:: StatisticsQuery!! Nicht Collection! Option .mostRecent. Achtung, unten auch setzen!!
let query = HKStatisticsCollectionQuery(quantityType: bodyMassType,
quantitySamplePredicate: nil,
options: [.mostRecent],
anchorDate: anchorDate,
intervalComponents: interval)
query.initialResultsHandler = { _, results, error in
guard let results = results else {
print("ERROR")
return
}
results.enumerateStatistics(from: startDate, to: now) { statistics, _ in
// hier wieder .mostRecent!
if let sum = statistics.mostRecentQuantity() {
let bodyMassValue = sum.doubleValue(for: HKUnit.gramUnit(with: .kilo)).roundToDecimal(2)
completion(bodyMassValue, statistics.startDate)
return
}
}
}
healthStore.execute(query)
}
This loads data from the last n
days and returns bodyMass as well as the date
Upvotes: 2