Class

HKStatisticsCollectionQuery

A query that performs multiple statistics queries over a series of fixed-length time intervals, and returns the results.

Declaration

@interface HKStatisticsCollectionQuery : HKQuery

Overview

Statistics collection queries are often used to produce data for graphs and charts. For example, you might create a statistics collection query that calculates the total number of steps for each day or the average heart rate for each hour. Like observer queries, collection queries can also act as long-running queries, receiving updates when matching samples are added to or removed from the HealthKit store.

Statistics collection queries use an anchor point and a time interval to partition the set of matching samples into collections. The anchor point defines an arbitrary starting point. The position of this point often does not matter. It could be in the future or in the past. Time intervals will extend away from this anchor point in both directions.

For example, if you use a 1-day time interval, the anchor point defines the time when each collection begins. The exact date for the anchor point doesn’t matter. It could be 3:34 am, January 1, 1970 or 3:34 am, March 15, 2065. In both cases, the statistics collection query partitions the matching samples into days, starting each day at 3:34 am.

You can use statistics collection queries only with quantity samples. If you want to calculate statistics over workouts or correlation samples, you must perform the appropriate query and process the data yourself.

Statistics collection queries are mostly immutable. You can assign the query’s initialResultsHandler and statisticsUpdateHandler properties after instantiating the object. All other properties must be set when you instantiate the object, and they cannot change.

For more information about statistics queries, see HKStatisticsQuery.

Executing Statistics Queries

You create a sample query by calling the statisticsUpdateHandler initializer. After the query is instantiated, you run it by calling the health store’s executeQuery: method. This method runs the query on a anonymous background queue. When the query is complete, it executes the results handler on the same background queue (but not necessarily on the same thread). Typically, you dispatch these results back to the main queue to update your user interface.

The following sample code shows how to build a statistics collection query and process the results.

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

This sample demonstrates calculating per-week step totals using a statistics collection query. This code starts by creating a 1-week time interval. Next, it sets the anchor date to Monday morning at 3:00 a.m. Because the interval is 1 week long, the anchor’s exact date doesn’t matter. Each set of statistics represents exactly 1 week, starting on Monday at 3:00 a.m.

Next, the sample creates the quantity type for step counts and then creates the query itself. In contrast with how you create other queries, you do not set the callback block when you instantiate a statistics collection query. Instead, you can either set the initial result handler or the statistics update handler (or both) as needed for your app. In this case, the sample code just sets the initial results handler, letting it calculate statistics over the samples currently stored in HealthKit.

Inside the result handler’s block, the code checks to see whether an error has occurred. If it doesn’t find an error, it calculates the start and end times for a 3-month window and then iterates over all the time intervals in that window. The statistics collection passes the enumeration block a statistics object for each time interval between the start and end dates. However, if the time interval does not contain any samples, the provided statistics’s sumQuantity method returns nil. Therefore, the sample must check to see whether it has a valid quantity. If it does, it plots the data; otherwise, it simply skips that time interval.

Since we did not provide an update results handler, when the initial results block is done processing the data, the query stops automatically. If we had provided an update manager, the statistics collection query would continue to monitor the HealthKit store after it had generated the initial results.

After the sample defines the result handler’s block, the query is complete. The sample code simply executes this query using the HealthKit store.

Topics

Creating Statistics Collection Objects

- initWithQuantityType:quantitySamplePredicate:options:anchorDate:intervalComponents:

Initializes a statistics collection query to perform the specified calculations over a set of time intervals.

Getting and Setting Results Handlers

initialResultsHandler

The results handler for this query’s initial results.

statisticsUpdateHandler

The results handler for monitoring updates to the HealthKit store.

Getting Property Data

anchorDate

The anchor date for the collection’s time intervals.

intervalComponents

The date components that define the time interval for each statistics object in the collection.

options

A list of options that define the type of statistical calculations performed and the way in which data from multiple sources are merged.

Relationships

Inherits From

See Also

Calculating Statistics

HKStatisticsQuery

A query that performs statistical calculations over a set of matching quantity samples, and returns the results.

HKStatistics

An object that represents the result of calculating the minimum, maximum, average, or sum over a set of samples from the HealthKit store.

HKStatisticsCollection

An object that manages a collection of statistics; each statistics object represents the data calculated over a separate time interval.

HKStatisticsOptions

Options for specifying the statistic to calculate.