Class

HKStatisticsCollectionQuery

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

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 execute(_:) 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.

let calendar = NSCalendar.currentCalendar()
 
let interval = NSDateComponents()
interval.day = 7
 
// Set the anchor date to Monday at 3:00 a.m.
let anchorComponents = calendar.components([.Day, .Month, .Year, .Weekday], fromDate: NSDate())
 
 
let offset = (7 + anchorComponents.weekday - 2) % 7
anchorComponents.day -= offset
anchorComponents.hour = 3
 
guard let anchorDate = calendar.dateFromComponents(anchorComponents) else {
    fatalError("*** unable to create a valid date from the given components ***")
}
 
guard let quantityType = HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount) else {
    fatalError("*** Unable to create a step count type ***")
}
 
// Create the query
let query = HKStatisticsCollectionQuery(quantityType: quantityType,
                                        quantitySamplePredicate: nil,
                                        options: .CumulativeSum,
                                        anchorDate: anchorDate,
                                        intervalComponents: interval)
 
// Set the results handler
query.initialResultsHandler = {
    query, results, error in
    
    guard let statsCollection = results else {
        // Perform proper error handling here
        fatalError("*** An error occurred while calculating the statistics: \(error?.localizedDescription) ***")
    }
    
    let endDate = NSDate()
    
    guard let startDate = calendar.dateByAddingUnit(.Month, value: -3, toDate: endDate, options: []) else {
        fatalError("*** Unable to calculate the start date ***")
    }
    
    // Plot the weekly step counts over the past 3 months
    statsCollection.enumerateStatisticsFromDate(startDate, toDate: endDate) { [unowned self] statistics, stop in
        
        if let quantity = statistics.sumQuantity() {
            let date = statistics.startDate
            let value = quantity.doubleValueForUnit(HKUnit.countUnit())
            
            // Call a custom method to plot each data point.
            self.plotWeeklyStepCount(value, forDate: date)
        }
    }
}
 
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

init(quantityType: HKQuantityType, quantitySamplePredicate: NSPredicate?, options: HKStatisticsOptions = [], anchorDate: Date, intervalComponents: DateComponents)

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

Getting and Setting Results Handlers

Getting Property Data

var anchorDate: Date

The anchor date for the collection’s time intervals.

var intervalComponents: DateComponents

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

var options: HKStatisticsOptions

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

Conforms To

See Also

Calculating Statistics

class HKStatisticsQuery

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

class HKStatistics

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

class HKStatisticsCollection

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

struct HKStatisticsOptions

Options for specifying the statistic to calculate.