Class

HKSampleQuery

A general-purpose query that returns a snapshot of all the matching samples currently saved in the HealthKit store.

Overview

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

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.

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.

Setting Limits

let HKObjectQueryNoLimit: Int

A value indicating that the query returns all the matching samples in the HealthKit store.

Relationships

Inherits From

Conforms To

See Also

Common Query Types

class HKQuantitySeriesSampleQuery

A query that accesses the series data associated with a quantity sample.

class HKAnchoredObjectQuery

A query that returns only recent changes to the HealthKit store, including a snapshot of new changes and continuous monitoring as a long-running query.

class HKObserverQuery

A long-running query that monitors the HealthKit store and updates your app whenever a matching sample is saved to or deleted from the HealthKit store.

class HKCorrelationQuery

A query that performs complex searches based on the correlation’s contents, and returns a snapshot of all matching samples.

class HKDocumentQuery

A query that returns a snapshot of all matching documents currently saved in the HealthKit store.

class HKQuery

An abstract class for all the query classes in HealthKit.