reef
reef

Reputation: 147

Query HealthKit for total steps for the day

I am calling a function and have been trying to figure out how I can update my app to reflect the total steps for the day. Currently, the code I have only gives me the most recent quantity of steps that has been recorded. I am having trouble understanding how to use the HKStatisticsQuery but this is the function I have at the moment that is giving me the most recent results.

-(void)updateStepsLabel{
        // Query to get the user's latest steps, if it exists.
HKQuantityType *stepsType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];

[_healthStore aapl_mostRecentQuantitySampleOfType:stepsType predicate:nil completion:^(HKQuantity *mostRecentQuantity, NSError *error) {
    if (!mostRecentQuantity) {
        NSLog(@"Either an error occured fetching the user's steps information or none has been stored yet. In your app, try to handle this gracefully.");

        dispatch_async(dispatch_get_main_queue(), ^{
            self.todaysStepValueLabel.text = NSLocalizedString(@"Not available", nil);
        });
    }
    else {
        // Determine the steps in the required unit.
        HKUnit *stepUnit = [HKUnit countUnit];
        double usersWeight = [mostRecentQuantity doubleValueForUnit:stepUnit];

        // Update the user interface.
        dispatch_async(dispatch_get_main_queue(), ^{
            self.todaysStepValueLabel.text = [NSNumberFormatter localizedStringFromNumber:@(usersWeight) numberStyle:NSNumberFormatterNoStyle];
            self.todaysStepValueLabel.textColor = [UIColor blackColor];
            self.todaysStepValueLabel.font = [UIFont systemFontOfSize:25];


        });
    }
}];

}

Upvotes: 1

Views: 2279

Answers (2)

Umair Afzal
Umair Afzal

Reputation: 5039

Here I am posting an answer with Swift code, I hope you would be able to convert it into Obj-c

I have written the below function in a class with definition like this

class MyHealthStore: HKHealthStore { }

.

func TodayTotalSteps(completion: (stepRetrieved: Double) -> Void) {

    let type = HKSampleType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount) // The type of data we are requesting

    let calendar = NSCalendar.currentCalendar()
    let interval = NSDateComponents()
    interval.day = 1

    let anchorComponents = calendar.components([.Day , .Month , .Year], fromDate: NSDate())
    anchorComponents.hour = 0
    let anchorDate = calendar.dateFromComponents(anchorComponents)

    let stepsQuery = HKStatisticsCollectionQuery(quantityType: type!, quantitySamplePredicate: nil, options: .CumulativeSum, anchorDate: anchorDate!, intervalComponents: interval)

    stepsQuery.initialResultsHandler = {query, results, error in
        let endDate = NSDate()

        var totalSteps = 0.0
        let startDate = calendar.dateByAddingUnit(.Day, value: 0, toDate: endDate, options: [])
        if let myResults = results{  myResults.enumerateStatisticsFromDate(startDate!, toDate: endDate) { statistics, stop in
            if let quantity = statistics.sumQuantity(){
                //let date = statistics.startDate
                totalSteps = quantity.doubleValueForUnit(HKUnit.countUnit())
               // print("\(date): steps = \(steps)")
            }
            self.todayManuallyAddedSteps({ (manuallSteps, error) in
                if error != nil {
                    print(error)
                } else {
                   totalSteps = totalSteps - manuallSteps
                    completion(stepRetrieved: totalSteps)
                    return
                }
            })
            //completion(stepRetrieved: totalSteps)

            }
        } else {
            // mostly not executed
            completion(stepRetrieved: totalSteps)
        }
    }
    executeQuery(stepsQuery)
}

And if you want to truncate manually added steps use this function

func todayManuallyAddedSteps(completion: (Double, NSError?) -> () )
{
    let type = HKSampleType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount) // The type of data we are requesting

    let date = NSDate()
    let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
    let newDate = cal.startOfDayForDate(date)
    let predicate = HKQuery.predicateForSamplesWithStartDate(newDate, endDate: NSDate(), options: .None) // Our search predicate which will fetch all steps taken today

    // The actual HealthKit Query which will fetch all of the steps and add them up for us.

    let query = HKSampleQuery(sampleType: type!, predicate: predicate, limit: 0, sortDescriptors: nil) { query, results, error in
        var steps: Double = 0

        if results?.count > 0
        {
            for result in results as! [HKQuantitySample]
            {
                // checking and adding manually added steps
                if result.sourceRevision.source.name == "Health" {
                    // these are manually added steps

                    steps += result.quantity.doubleValueForUnit(HKUnit.countUnit())
                }
                else{
                    // these are auto detected steps which we do not want from HKSampleQuery
                }
            }
            completion(steps, error)

            return
        } else {
            // mostly not executed
            completion(steps, error)
        }
    }
    executeQuery(query)
}

and here is how to call it

 MyHealthStore.sharedHealthStore.TodayTotalSteps { (stepRetrieved) in 
     print(stepRetrieved)
 }

I hope its helps, let me know if you find any difficulty.

Upvotes: 1

Rajat
Rajat

Reputation: 11127

Here is the code which is given in the document of HKStatisticsCollectionQuery

NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *interval = [[NSDateComponents alloc] init];
interval.day = 7;

// Set the anchor date to Monday at 3:00 a.m.
NSDateComponents *anchorComponents =
[calendar components:NSCalendarUnitDay | NSCalendarUnitMonth |
 NSCalendarUnitYear | NSCalendarUnitWeekday fromDate:[NSDate date]];

NSInteger offset = (7 + anchorComponents.weekday - 2) % 7;
anchorComponents.day -= offset;
anchorComponents.hour = 3;

NSDate *anchorDate = [calendar dateFromComponents:anchorComponents];

HKQuantityType *quantityType =
[HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];

// Create the query
HKStatisticsCollectionQuery *query =
[[HKStatisticsCollectionQuery alloc]
 initWithQuantityType:quantityType
 quantitySamplePredicate:nil
 options:HKStatisticsOptionCumulativeSum
 anchorDate:anchorDate
 intervalComponents:interval];

// Set the results handler
query.initialResultsHandler =
^(HKStatisticsCollectionQuery *query, HKStatisticsCollection *results, NSError *error) {

    if (error) {
         // Perform proper error handling here
        NSLog(@"*** An error occurred while calculating the statistics: %@ ***",
              error.localizedDescription);
        abort();
    }

    NSDate *endDate = [NSDate date];
    NSDate *startDate = [calendar
                         dateByAddingUnit:NSCalendarUnitMonth
                         value:-3
                         toDate:endDate
                         options:0];

    // Plot the weekly step counts over the past 3 months
    [results
     enumerateStatisticsFromDate:startDate
     toDate:endDate
     withBlock:^(HKStatistics *result, BOOL *stop) {

         HKQuantity *quantity = result.sumQuantity;
         if (quantity) {
             NSDate *date = result.startDate;
             double value = [quantity doubleValueForUnit:[HKUnit countUnit]];

             // Call a custom method to plot each data point.
             [self plotWeeklyStepCount:value forDate:date];
         }

     }];
};

[self.healthStore executeQuery:query];

In the given code there are 2 dates mentioned

NSDate *endDate = [NSDate date];
NSDate *startDate = [calendar
                     dateByAddingUnit:NSCalendarUnitMonth
                     value:-3
                     toDate:endDate
                     options:0];

Change the startDate and endDate as per your requirement.

Upvotes: 0

Related Questions