HealthKit Queries and Sample Writes
Covers one-shot reads, rollups for charts, and writing new samples, plus the descriptor-based Swift Concurrency APIs that replace the old callback-based query classes.
When to Use
Use this skill when you're:
- Reading data from HealthKit for a one-shot display (today's steps, most recent heart rate)
- Computing daily, hourly, or weekly rollups for charts
- Writing new
HKQuantitySample,HKCategorySample, orHKWorkoutsamples to the store - Choosing between
HKSampleQuery,HKStatisticsQuery,HKStatisticsCollectionQuery, and their descriptor variants - Modernizing callback-based query code to Swift Concurrency descriptors
Example Prompts
Questions you can ask your assistant that will draw from this skill:
- "How do I fetch today's total step count with Swift Concurrency?"
- "I need daily calorie rollups for the last 30 days — which query should I use?"
- "Why is
stats.sumQuantity()returning nil when I asked for an average?" - "How do I save a weight measurement and make sure it's marked as user-entered?"
- "My
HKStatisticsCollectionQuerydoesn't work with workouts — what's the alternative?"
What This Skill Provides
Query Selection
- A decision tree for
HKSampleQueryvs.HKStatisticsQueryvs.HKStatisticsCollectionQuery - When to switch to Sync and Background instead (change tracking, background delivery)
- Why descriptors (iOS 15.4+) are preferred over the classic callback classes
Canonical Patterns
- Reading raw samples with a predicate, sort, and limit
- A single aggregate over a window (total steps today)
- Rollups over intervals for a chart (daily steps, last 30 days)
- Writing quantity samples with metadata
HKStatisticsOptions Rules
- Which accessor goes with which option (
.cumulativeSum→sumQuantity(),.discreteAverage→averageQuantity(), and so on) - Why cumulative and discrete options can't be combined
- Why
HKStatisticsCollectionQueryaccepts only quantity samples, and what to do for workouts or correlations
Writes and Performance
- Batch save rules and sample-granularity recommendations
- Why samples are immutable, and how to "update" one by deleting and replacing it
- Memory-safe query practices (always narrow by date, and set a
limit:) - When to fall back to
HKAnchoredObjectQueryDescriptorwith pagination
Key Pattern
Prefer async descriptors. They replace the callback-based query classes with typed, Sendable variants that inherit the caller's actor context.
let predicate = HKSamplePredicate<HKQuantitySample>.quantitySample(
type: HKQuantityType(.stepCount),
predicate: HKQuery.predicateForSamples(withStart: startOfDay, end: nil)
)
let descriptor = HKStatisticsQueryDescriptor(
predicate: predicate,
options: .cumulativeSum
)
let statistics = try await descriptor.result(for: store)
let steps = statistics?.sumQuantity()?.doubleValue(for: .count()) ?? 0There's no completion handler and no manual stop(query) cleanup, and generic typing catches wrong-sample-type bugs at compile time.
Documentation Scope
This page documents the queries skill (in the axiom-health suite). The skill also holds the full decision tree, an HKStatisticsOptions reference table, which accessors return nil for each option, and common mistakes.
- For the
HKWorkoutSessionandHKLiveWorkoutBuilderlifecycle, see Workouts
Related
- Fundamentals – Read first for the
HKObjectTypehierarchy and the quantity-versus-category distinction - Authorization and Privacy – Why an empty result can mean a denied read, and how authorization affects error handling
- Sync and Background – The next step when one-shot reads aren't enough and you need to track changes
- Swift 6 Concurrency – Actor isolation patterns that affect how you handle descriptor results
- SwiftUI Architecture –
@Observableview models for renderingHKStatisticsCollectionresults in charts
Resources
WWDC: 2020-10664 (Getting started with HealthKit), 2022-10005 (What's new in HealthKit)
Docs: /healthkit/reading-data-from-healthkit, /healthkit/queries, /healthkit/running-queries-with-swift-concurrency, /healthkit/hksamplequerydescriptor, /healthkit/hkstatisticsquerydescriptor, /healthkit/hkstatisticscollectionquerydescriptor, /healthkit/hkstatisticsoptions, /healthkit/hkstatistics, /healthkit/hkstatisticscollection, /healthkit/hksamplepredicate, /healthkit/saving-data-to-healthkit