Search code examples
iosswifthealthkit

HealthKit Swift getting today's steps


I am making a swift iOS app that integrates with a user's step count as reported by the Health app. I can easily find the user's step count in the last hour, using this as my predicate:

let anHourBeforeNow: NSDate = NSDate().dateByAddingTimeInterval(-60 * 60)
let predicate = HKQuery.predicateForSamplesWithStartDate(anHourBeforeNow, endDate: NSDate(), options: .None)

And I have the rest down, so I can successfully access the user's step count for the last hour. But how can I access the user's step data since the day began, like the Health app displays in the steps section?

I am trying to do something like this:

let date = NSDate()
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let newDate = cal.startOfDayForDate(date)
let predicate = HKQuery.predicateForSamplesWithStartDate(newDate, endDate: NSDate(), options: .None)

but this code does not adjust for time zone (so it gives me the beginning of the day in UTC, not the beginning of the day where the user is) and I am also getting highly inflated step counts (for reasons unknown).

So how can I get the user's step count for the current day, with the same number of steps as reported in Health, like pictured here:enter image description here


Solution

  • 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];