Xerion
Xerion

Reputation: 3281

iOS HealthKit today's step count is always 0 (but trailing days are OK)

In our app, we query the HealthKit for trailing 7 days' worth of step counts, summed daily, with a pivot of midnight. So the range is D-6 midnight until tomorrow's midnight (since we wanted today's steps until now).

Is that it works, and we are always able to get the past 6 day's data, except today's is always 0.

But the weird part is that, if we then open the default iHealth app that came with iOS 8.0, it calculates the health data and shows today's steps in the chart. And then, if we reopen our app and reload the chart data, today's steps is miraculously there, matching what "iHealth" shows.

So does iPhone automatically generate daily steps count only at midnight, and caches it or something? Is there a separate call we need to make in order to calculate today's data or something prior to retrieving any health metrics?

Here's the function we call to get the data:

func queryDailyStats(metric: NSString!, handler: ([NSDate: Int] -> Void)!) {
    let quantityType = HKObjectType.quantityTypeForIdentifier(metric)
    let calendar = NSCalendar.currentCalendar()
    let now = NSDate()
    let preservedComponents: NSCalendarUnit = (.CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay)
    let midnight: NSDate! = calendar.dateFromComponents(calendar.components(preservedComponents, fromDate:now))
    let dailyInterval = NSDateComponents()
    dailyInterval.day = 1

    let tomorrow = calendar.dateByAddingUnit(.MonthCalendarUnit, value: 1, toDate: midnight, options: nil)
    let oneMonthAgo = calendar.dateByAddingUnit(.MonthCalendarUnit, value: -1, toDate: midnight, options: nil)
    let oneWeekAgo = calendar.dateByAddingUnit(.DayCalendarUnit, value: -6, toDate: midnight, options: nil) // only need to start from 6 days back

    // need tomorrow's midnight as end date to get all of today's data
    let predicate = HKQuery.predicateForSamplesWithStartDate(oneWeekAgo, endDate: tomorrow, options: .None)

    let query = HKStatisticsCollectionQuery(
        quantityType: quantityType,
        quantitySamplePredicate: predicate,
        options: .CumulativeSum,
        anchorDate: midnight,
        intervalComponents: dailyInterval
    )

    query.initialResultsHandler = { query, results, error -> Void in
        var data:[NSDate: Int] = [:]
        if error != nil {
            println(error)
        } else {
            results.enumerateStatisticsFromDate(oneWeekAgo, toDate: midnight) { statistics, stop in
                if let quantity = statistics.sumQuantity() {
                    let date = statistics.startDate
                    let value = Int(quantity.doubleValueForUnit(HKUnit.countUnit()))

                    data[date] = value
                }
            }
        }

        handler(data)
    }

    self.healthKitStore.executeQuery(query)
}

Upvotes: 3

Views: 2844

Answers (4)

Nil Rathod
Nil Rathod

Reputation: 468

Try this code u just change the start date and End date.

-(void) getQuantityResult {
    NSInteger limit = 0;
    NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:currentDate endDate:[[NSDate date]dateByAddingTimeInterval:60*60*24*3] options:HKQueryOptionStrictStartDate];
    
    NSString *endKey =  HKSampleSortIdentifierEndDate;
    NSSortDescriptor *endDate = [NSSortDescriptor sortDescriptorWithKey: endKey ascending: NO];
    
    HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType[HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]
                                                           predicate: predicate
                                                               limit: limit
                                                     sortDescriptors: @[endDate]
                                                      resultsHandler:^(HKSampleQuery *query, NSArray* results, NSError *error){
                                                            dispatch_async(dispatch_get_main_queue(), ^{
                                                              // sends the data using HTTP
                                                              int dailyAVG = 0;
                                                              for(HKQuantitySample *samples in results)
                                                                           {
                                                                  dailyAVG += [[samples quantity] doubleValueForUnit:[HKUnit countUnit]];
                                                               }
                                                              lblPrint.text = [NSString stringWithFormat:@"%d",dailyAVG];
                                                              NSLog(@"%@",lblPrint.text);
                                                              NSLog(@"%@",@"Done");
                                                          });
                                                      }];
    [self.healthStore executeQuery:query];
}

Upvotes: 1

Mario Hendricks
Mario Hendricks

Reputation: 757

If you just want current or recent step count and distance data, you should use the Core Motion CMPedometer class instead of HealthKit. The interface is much easier and data is returned quickly and accurately. I had the same problem and switched to the Core Motion approach to solve it.

Upvotes: 1

drdaanger
drdaanger

Reputation: 360

Are you simply not enumerating it, or do you just not see the data? If the former, try changing results.enumerateStatisticsFromDate(oneWeekAgo, toDate: midnight)… to results.enumerateStatisticsFromDate(oneWeekAgo, toDate: tomorrow)….

You probably also want to change your definition of tomorrow to be one day from midnight today, instead of one month!

Upvotes: 0

Allan
Allan

Reputation: 7353

Your query only has an initialResultsHandler. To get HealthKit to import steps from the motion co-processor more frequently when your app is running, you need to either set an updateHandler on this query or open an HKObserverQuery for steps.

Upvotes: 0

Related Questions