How to get Apple health data by date wise?
Use HKStatisticsCollectionQuery
to fetch data from a certain period. Here is an example showing how to fetch steps for the last 30 days:
private let healthStore = HKHealthStore()
private let stepsQuantityType = HKQuantityType.quantityType(forIdentifier: .stepCount)!
func importStepsHistory() {
let now = Date()
let startDate = Calendar.current.date(byAdding: .day, value: -30, 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: stepsQuantityType,
quantitySamplePredicate: nil,
options: [.cumulativeSum],
anchorDate: anchorDate,
intervalComponents: interval
)
query.initialResultsHandler = { _, results, error in
guard let results = results else {
log.error("Error returned form resultHandler = \(String(describing: error?.localizedDescription))")
return
}
results.enumerateStatistics(from: startDate, to: now) { statistics, _ in
if let sum = statistics.sumQuantity() {
let steps = sum.doubleValue(for: HKUnit.count())
print("Amount of steps: \(steps), date: \(statistics.startDate)")
}
}
}
healthStore.execute(query)
}
HealthKit Swift getting today's steps
Here is the right way using HKStatisticsCollectionQuery courtesy of the direction from the code above.
This is written in Swift 3 so you may have to convert some of the code back to 2.3 or 2 if not on 3 yet.
Swift 3
func retrieveStepCount(completion: (stepRetrieved: Double) -> Void) {
// Define the Step Quantity Type
let stepsCount = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)
// Get the start of the day
let date = Date()
let cal = Calendar(identifier: Calendar.Identifier.gregorian)
let newDate = cal.startOfDay(for: date)
// Set the Predicates & Interval
let predicate = HKQuery.predicateForSamples(withStart: newDate, end: Date(), options: .strictStartDate)
var interval = DateComponents()
interval.day = 1
// Perform the Query
let query = HKStatisticsCollectionQuery(quantityType: stepsCount!, quantitySamplePredicate: predicate, options: [.cumulativeSum], anchorDate: newDate as Date, intervalComponents:interval)
query.initialResultsHandler = { query, results, error in
if error != nil {
// Something went Wrong
return
}
if let myResults = results{
myResults.enumerateStatistics(from: self.yesterday, to: self.today) {
statistics, stop in
if let quantity = statistics.sumQuantity() {
let steps = quantity.doubleValue(for: HKUnit.count())
print("Steps = \(steps)")
completion(stepRetrieved: steps)
}
}
}
}
storage.execute(query)
}
Objective-C
HKQuantityType *type = [HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
NSDate *today = [NSDate date];
NSDate *startOfDay = [[NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian] startOfDayForDate:today];
NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startOfDay endDate:today options:HKQueryOptionStrictStartDate];
NSDateComponents *interval = [[NSDateComponents alloc] init];
interval.day = 1;
HKStatisticsCollectionQuery *query = [[HKStatisticsCollectionQuery alloc] initWithQuantityType:type quantitySamplePredicate:predicate options:HKStatisticsOptionCumulativeSum anchorDate:startOfDay intervalComponents:interval];
query.initialResultsHandler = ^(HKStatisticsCollectionQuery * _Nonnull query, HKStatisticsCollection * _Nullable result, NSError * _Nullable error) {
if (error != nil) {
// TODO
} else {
[result enumerateStatisticsFromDate:startOfDay toDate:today withBlock:^(HKStatistics * _Nonnull result, BOOL * _Nonnull stop) {
HKQuantity *quantity = [result sumQuantity];
double steps = [quantity doubleValueForUnit:[HKUnit countUnit]];
NSLog(@"Steps : %f", steps);
}];
}
};
[self.storage executeQuery:query];
Get devices from HealthKit
I found solution. I will query HKSample and property HKDevice in HKSample contain information about device.
let group = DispatchGroup()
for source in sources {
let sourceModel = SourceHealthKitModel(source: source)
group.enter()
let type = HKQuantityType.quantityType(forIdentifier: .stepCount)
let predicate = HKQuery.predicateForObjects(from: source)
let query = HKSampleQuery(sampleType: type!, predicate: predicate, limit: 1, sortDescriptors: nil) { (query, results, error) in
if let sample = results?.first {
sourceModel.sample = sample
self?.dataSources.append(sourceModel)
}
group.leave()
}
HKHealthStore().execute(query)
}
group.notify(queue: .main) {
self?.tableView.reloadData()
}
How to get HealthKit total steps for previous dates
You should use HKStatisticsQuery
or HKStatisticsCollectionQuery
instead of HKSampleQuery
. The statistics queries will de-deuplicate overlapping step samples from different sources to ensure that you do not double-count them. You can find documentation for them here and here.
Related Topics
How to Implement a Spritekit Timer
Adding Activity Indicator to Uialertview
Healthkit Error: Missing Com.Apple.Developer.Healthkit Entitlement
Swift Uisearchcontroller Wired Up in Core Data Project, App Runs, But Search Not Updating
How to Implement a Thread Safe Hashtable (Phonebook) Data Structure in Swift
Why Are Iboutlets Optionals After Swift 5 Migration
Swift Draw Shadow to a Uibezier Path
Building User Database Model in Firebase
Dispatchqueue:Cannot Be Called with Ascopy = No on Non-Main Thread
Creating Gif Image Color Maps in iOS 11
Executefetchrequest Doesn't Return the Nsmanagedobject Subclass
"An Error Occurred While Accessing the Keychain" When Signing in Using Firebase