Class

HKSampleQuery

HealthKit uses sample queries to search for sample data in the HealthKit store. You can use sample queries to search for any concrete subclasses of the HKSample class, including HKCategorySample, HKCorrelation, HKQuantitySample, and HKWorkout objects.

Overview

The sample query returns sample objects that match the provided type and predicate. You can provide a sort order for the returned samples, or limit the number of samples returned. Other query classes can be used to perform more specialized searches and calculations. For more information, see HKQuery.

Sample queries are immutable: The query’s properties are set when the query is first created. They cannot change.

Executing Queries

You create a sample query by calling the init(sampleType:predicate:limit:sortDescriptors:resultsHandler:) initializer. After the query is instantiated, you run it by calling the HealthKit store’s execute(_:) method. This method runs the query on an anonymous background queue. When the query is complete, it executes the results handler on the background queue. Typically, you dispatch these results back to the main queue to update your user interface.

Listing 1 shows how to build a query and process the results. This code is taken from the AAPLJournalViewController.m file in the sample code project Fit: Store and Retrieve HealthKit Data.

Listing 1

Writing HealthKit data

let calendar = NSCalendar.currentCalendar()
let now = NSDate()
let components = calendar.components([.Year, .Month, .Day], fromDate: now)
 
guard let startDate = calendar.dateFromComponents(components) else {
    fatalError("*** Unable to create the start date ***")
}
 
let endDate = calendar.dateByAddingUnit(.Day, value: 1, toDate: startDate, options: [])
 
guard let sampleType = HKSampleType.quantityTypeForIdentifier(HKQuantityTypeIdentifierDietaryEnergyConsumed) else {
    fatalError("*** This method should never fail ***")
}
 
let predicate = HKQuery.predicateForSamplesWithStartDate(startDate, endDate: endDate, options: .None)
 
let query = HKSampleQuery(sampleType: sampleType, predicate: predicate, limit: Int(HKObjectQueryNoLimit), sortDescriptors: nil) {
    query, results, error in
    
    guard let samples = results as? [HKQuantitySample] else {
        fatalError("An error occured fetching the user's tracked food. In your app, try to handle this error gracefully. The error was: \(error?.localizedDescription)");
    }
    
    dispatch_async(dispatch_get_main_queue()) {
        
        foodItems.removeAll()
        
        for sample in samples {
            
            guard let foodName =
                sample.metadata?[HKMetadataKeyFoodType] as? String else {
                    // if the metadata doesn't record the food type, just skip it.
                    break
            }
            
            let joules = sample.quantity.doubleValueForUnit(HKUnit.jouleUnit())
            
            let foodItem = AAPLFoodItem.foodItemWithName(foodName, joules: joules)
            
            foodItems.append(foodItem)
        }
        
        tableView.reloadData()
    }
}
 
healthStore.executeQuery(query)

The above sample code starts by calculating the start and end dates for the desired time interval, to produce a 24-hour period, starting at the previous midnight. Next, it defines a sample type for dietary energy consumed, and a predicate that filters out any samples that don’t fall within the desired time interval.

With the sample type and predicate created, it builds the query. This query returns any samples measuring dietary energy consumed that fall within the time frame. There is no limit placed on the number of samples it returns, and the results are not sorted.

The results handler starts by checking to see whether an error occurred. If there is an error, it prints a log message to the console and aborts. Otherwise, it dispatches back to the main thread to update the UI.

The dispatch block begins by clearing the view controller’s array of food items. Next, it iterates over each result, grabbing the name of the food (from the metadata) and the amount of energy (in joules). It uses these values to create a new food item, which it adds to the food item array.

After all the results have been processed, the results handler asks the table view to load the new data.

After the results handler’s block is defined, the query is complete. This query is then executed using the HealthKit store.

Subclassing Notes

Like many HealthKit classes, the HKSampleQuery class should not be subclassed.

Topics

Getting Property Data

var limit: Int

The maximum number of samples that this query returns.

var sortDescriptors: [NSSortDescriptor]?

The sort descriptors that specify the order of the results returned by this query.

Constants

Sample Query Limits

A constant used to limit the number of results returned by a sample query.

Relationships

Inherits From

Conforms To