---
title: "HealthKit Queries"
canonical: "https://aifitnessapi.com/healthkit-queries"
type: "cluster-index"
pages: "9"
last_reviewed: "2026-10-03"
publisher: "AIFitnessAPI"
---

# HealthKit Queries

> 9 pages. Each entry below shows the question the page owns, followed by its answer capsule.

## HKSampleQuery: a one-time snapshot of matching samples

- Question: HKSampleQuery
- HTML: https://aifitnessapi.com/healthkit-queries/hksamplequery
- Markdown: https://aifitnessapi.com/healthkit-queries/hksamplequery.md
- Last reviewed: 2026-10-03

HKSampleQuery is HealthKit's general-purpose read, which Apple describes as "a general query that returns a snapshot of all the matching samples currently saved in the HealthKit store." You give it a sample type, an optional predicate, a limit and optional sort descriptors, run it with HKHealthStore's execute(_:), and receive one array of samples on a background queue. It does not keep watching the store, cannot be changed once created, and does not compute totals: use HKAnchoredObjectQuery to follow changes and HKStatisticsQuery for sums or averages.

## HealthKit query predicates: predicateForSamples, HKQueryOptions and HKSamplePredicate

- Question: HKQuery.predicateForSamples(withStart:end:options:)
- HTML: https://aifitnessapi.com/healthkit-queries/healthkit-query-predicates
- Markdown: https://aifitnessapi.com/healthkit-queries/healthkit-query-predicates.md
- Last reviewed: 2026-10-03

HKQuery.predicateForSamples(withStart:end:options:) builds the date-window NSPredicate most HealthKit queries use, and its options decide what counts as inside the window. With no options it matches any sample that overlaps the window: Apple's equivalent format string requires the sample's end date to be at or after the window start and its start date to be before the window end, so a sample that began before midnight still matches today. HKQueryOptions.strictStartDate requires the sample's start to fall inside the window and strictEndDate requires its end to. Because HealthKit converts predicates to SQL, only its own key paths and factory methods work, and the async query descriptors wrap a type and a predicate together as HKSamplePredicate.

## HKStatisticsQuery: one sum, average or extreme over a window

- Question: HKStatisticsQuery
- HTML: https://aifitnessapi.com/healthkit-queries/hkstatisticsquery
- Markdown: https://aifitnessapi.com/healthkit-queries/hkstatisticsquery.md
- Last reviewed: 2026-10-03

HKStatisticsQuery calculates one statistic over every quantity sample that matches a predicate: a sum for cumulative types such as steps, or a minimum, maximum, average or most recent value for discrete types such as heart rate. Apple documents that it works on quantity samples only, that a discrete option cannot be combined with a cumulative one, and that you must read the result with the accessor matching the option you asked for, so sumQuantity() returns nil unless the query used cumulativeSum. By default HealthKit merges data from all sources before calculating; the separateBySource option gives per-source values as well.

## HKStatisticsCollectionQuery: daily totals, anchorDate and intervalComponents

- Question: HKStatisticsCollectionQuery
- HTML: https://aifitnessapi.com/healthkit-queries/hkstatisticscollectionquery
- Markdown: https://aifitnessapi.com/healthkit-queries/hkstatisticscollectionquery.md
- Last reviewed: 2026-10-03

HKStatisticsCollectionQuery splits matching quantity samples into fixed-length time intervals and calculates a statistic for each one, which makes it the query behind a daily step chart or an hourly heart-rate average. Two values define the buckets: anchorDate sets where one interval starts, and Apple says its exact date does not matter, only the time of day it lands on, while intervalComponents sets the length, such as DateComponents(day: 1). Results arrive in initialResultsHandler as an HKStatisticsCollection you walk with enumerateStatistics(from:to:with:), and assigning statisticsUpdateHandler turns it into a long-running query that you must stop with stop(_:).

## HKAnchoredObjectQuery: new samples, deleted objects and the HKQueryAnchor

- Question: HKAnchoredObjectQuery
- HTML: https://aifitnessapi.com/healthkit-queries/hkanchoredobjectquery
- Markdown: https://aifitnessapi.com/healthkit-queries/hkanchoredobjectquery.md
- Last reviewed: 2026-10-03

HKAnchoredObjectQuery returns what has changed in the HealthKit store since a position you saved: new samples, deleted objects as HKDeletedObject, and a new HKQueryAnchor to keep for next time. Pass nil as the anchor on the first run to get everything currently stored, then pass the returned anchor on each later run to get only newer changes. Assign updateHandler before executing it and the same query keeps running and delivers further changes, which is why Apple says one anchored object query is often more efficient than separate sample and observer queries.

## HKObserverQuery and enableBackgroundDelivery: how the pair works

- Question: HKObserverQuery
- HTML: https://aifitnessapi.com/healthkit-queries/hkobserverquery-background-delivery
- Markdown: https://aifitnessapi.com/healthkit-queries/hkobserverquery-background-delivery.md
- Last reviewed: 2026-10-03

HKObserverQuery is a long-running query that tells you matching HealthKit data changed, and never what changed, so its update handler normally runs an HKAnchoredObjectQuery to fetch the new and deleted samples. By default, Apple says, it only returns results while your app is in the foreground; to be woken in the background you also call HKHealthStore's enableBackgroundDelivery(for:frequency:withCompletion:), where the frequency is a maximum, not a schedule. When a background delivery wakes you, Apple requires you to call the update handler's completion handler once you have processed the data, and says that if your app fails to respond three times HealthKit stops sending background updates.

## HealthKit async/await queries: HKSampleQueryDescriptor and the other descriptors

- Question: HKSampleQueryDescriptor
- HTML: https://aifitnessapi.com/healthkit-queries/healthkit-async-query-descriptors
- Markdown: https://aifitnessapi.com/healthkit-queries/healthkit-async-query-descriptors.md
- Last reviewed: 2026-10-03

HealthKit's query descriptors, such as HKSampleQueryDescriptor, HKAnchoredObjectQueryDescriptor and HKStatisticsCollectionQueryDescriptor, are Swift structures that run HealthKit queries with async/await instead of callbacks. Each takes HKSamplePredicate values that carry the sample type, so results come back typed, for example as an array of HKQuantitySample rather than of the base HKSample class. Call result(for:) for a one-shot snapshot, or results(for:) where a descriptor offers it for a long-running query that streams updates as an AsyncSequence. Apple lists them from iOS 15.4, iPadOS 15.4, Mac Catalyst 15.4, macOS 13.0 and watchOS 8.5.

## HKWorkoutRouteQuery: reading a workout's GPS route in batches

- Question: HKWorkoutRouteQuery
- HTML: https://aifitnessapi.com/healthkit-queries/hkworkoutroutequery
- Markdown: https://aifitnessapi.com/healthkit-queries/hkworkoutroutequery.md
- Last reviewed: 2026-10-03

HKWorkoutRouteQuery reads the CLLocation points stored in an HKWorkoutRoute sample and delivers them in batches: its data handler can run several times, and only the call where done is true means you have every location. Finding the route sample is a separate, earlier step, and Apple recommends an HKAnchoredObjectQuery for HKSeriesType.workoutRoute() filtered with HKQuery.predicateForObjects(from:) for the workout, because route samples can arrive after the workout is saved and can be replaced later. Apple notes that the stored locations are accurate within 50 meters and may need smoothing before you draw them.

## HKActivitySummaryQuery: reading Move, Exercise and Stand rings

- Question: HKActivitySummaryQuery
- HTML: https://aifitnessapi.com/healthkit-queries/hkactivitysummaryquery
- Markdown: https://aifitnessapi.com/healthkit-queries/hkactivitysummaryquery.md
- Last reviewed: 2026-10-03

HKActivitySummaryQuery reads HKActivitySummary objects, one per day, each holding the Move, Exercise and Stand ring values and goals. You filter it with date components rather than dates, using HKQuery.predicate(forActivitySummariesBetweenStart:end:) or predicateForActivitySummary(with:), and Apple requires those components to carry a valid calendar. Read access is requested with HKObjectType.activitySummaryType(), and summaries can be read but never saved. Since iOS 14.0, activityMoveMode tells you whether the Move ring measures active energy or Apple Move Time, so check it before labelling a Move value as calories.
