I want to get the step data of a user by using HealthKit. However, I want to make sure that data that has been entered manually is ignored. I found a solution where someone asked this question and I know what needs to be entered but I am unsure how to do this. Wherever I put this code I seem to get errors:
Here is my code:
func calculateSteps(completion: @escaping (HKStatisticsCollection?)-> Void) {
let stepType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!
let startDate = Calendar.current.date(byAdding: .day, value: -7, to: Date())
let anchorDate = Date.mondayAt12AM()
let daily = DateComponents(day: 1)
let predicate = HKQuery.predicateForSamples(withStart: startDate, end: Date(), options: .strictStartDate)
query = HKStatisticsCollectionQuery(quantityType: stepType, quantitySamplePredicate: predicate, options: .cumulativeSum, anchorDate: anchorDate, intervalComponents: daily)
query!.initialResultsHandler = { query, statisticsCollection, error in
completion(statisticsCollection)
}
if let healthStore = healthStore, let query = self.query {
healthStore.execute(query)
}
}
And this is the sort of code I need to implement in the predicate part.
let predicate = NSPredicate(format: "metadata.%K != YES", HKMetadataKeyWasUserEntered)
Where shall I put this code?
UPDATED:
I have the code running with no errors however when the function runs it comes out as 0. Any ideas?
import Foundation
import HealthKit
extension Date {
static func mondayAt12AM() -> Date {
return Calendar(identifier: .iso8601).date(from: Calendar(identifier: .iso8601).dateComponents([.yearForWeekOfYear, .weekOfYear], from: Date()))!
}
}
class HealthStore {
var healthStore: HKHealthStore?
var query: HKStatisticsCollectionQuery?
init() {
if HKHealthStore.isHealthDataAvailable() {
healthStore = HKHealthStore()
}
}
func calculateSteps(completion: @escaping (HKStatisticsCollection?)-> Void) {
let stepType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!
let startDate = Calendar.current.date(byAdding: .day, value: -7, to: Date())
let anchorDate = Date.mondayAt12AM()
let daily = DateComponents(day: 1)
let predicate = HKQuery.predicateForSamples(withStart: startDate, end: Date(), options: .strictStartDate)
let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates:
[.init(format: "metadata.%K == NO", HKMetadataKeyWasUserEntered), predicate]
)
query = HKStatisticsCollectionQuery(
quantityType: stepType,
quantitySamplePredicate: compoundPredicate,
options: .cumulativeSum,
anchorDate: anchorDate,
intervalComponents: daily)
query!.initialResultsHandler = { query, statisticsCollection, error in
completion(statisticsCollection)
}
if let healthStore = healthStore, let query = self.query {
healthStore.execute(query)
}
}
func requestAuthorization(completion: @escaping (Bool) -> Void) {
let stepType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!
guard let healthStore = self.healthStore else { return completion(false) }
healthStore.requestAuthorization(toShare: [], read: [stepType]) { (success, error) in
completion(success)
}
}
}
3
Answers
I would try to create an NSCompoundPredicate with both the predicates you want and use that while creating the query.
If you are still running into errors, please share the specific errors you see.
Create a compound predicate with your current predicate
You need to create one Compound Predicate with the current Predicate as sub Predicate. And in format set
metadata.%K != YES
(metadata.%K == NO
will not work here, because the value for the key could be YES, NO, or nil and nil implies NO).And then create a query using that Compound Predicate.
Here is the code Sample