Skip to content

v4.0.0

Choose a tag to compare

@kvs-coder kvs-coder released this 08 Oct 20:28

4.0.0 (2026-10-08)

⚠ BREAKING CHANGES

  • [String: Any].asMetadata is internal; build Metadata with Metadata.make(from:) or its literals.
  • workoutEffortRelationshipQuery throws. Corrupt anchor data throws invalidValue instead of restarting the query; unknown correlation type predicate identifiers throw invalidType; save(sample:) of a Workout with both swimming strokes and flights climbed completes with invalidValue.
  • save(sample:completion:) completes with (success, uuid, error). Sample requires uuid and identifier; Statistics and WorkoutEvent no longer conform to Sample. delete, addQuantity / addCategory and unrelateWorkoutEffort act on the stored sample with the payload's uuid, so send the uuid back in dictionaries.
  • QueryHandle replaces every query typealias (Query, SampleQuery, ObserverQuery, …) in reader return types, executeQuery/stopQuery and callbacks; Anchor is a Codable struct instead of HKQueryAnchor; ObjectType.original and the public collect(results:) factories are removed; samplesPredicate takes SamplePredicateOptions; HealthKit enums lose their description conformances. ADR 0004 lists every change and what the Flutter plugin must update.
  • decorators: Workout.Harmonized.description, Electrocardiogram.Harmonized.classification and WorkoutEvent.Harmonized.description return the corrected strings. Consumers comparing against the misspelled values must update them.
  • vision: VisionPrescription.Harmonized.dateIssuedTimestamp and expirationDateTimestamp are seconds since 1970 instead of milliseconds; divide old values by 1000. The Harmonized initializer gains rightEye, leftEye and brand.
  • metadata: Metadata is a struct of Metadata.Value instead of the .string/.date/.double enum, Metadata.original is replaced by internal conversion, and the JSON shape changes from {"string": {"dictionary": {...}}} to a flat object with dates as {"timestamp": seconds since 1970} and quantities as {"value", "unit"}. Dictionary literals keep compiling. The Flutter plugin must read and send the flat shape.
  • encoding: non-finite numbers in encoded() JSON change from "inf" / "-500.0" to "Infinity" / "-Infinity" / "NaN". Consumers that matched the old strings (or treated -500.0 as NaN) must parse the new ones, e.g. with double.parse in Dart.
  • category: audioExposureEvent samples now harmonize with description 'HKCategoryValueEnvironmentalAudioExposureEvent' and detail 'Momentary Limit' (previously 'HKCategoryValueAudioExposureEvent' / 'Load Environment'); the public description/detail extension on HKCategoryValueAudioExposureEvent is removed.
  • minimum deployment targets are now iOS 15 and watchOS 8; CocoaPods and Carthage are no longer supported (3.1.0 is the last CocoaPods release).

Features

  • activity-summary: move time, move mode, paused and current goals (4f41672)
  • api: fix misspelled names and honour the device when adding samples to a workout (3a39356)
  • attachments: list, read, add and remove sample attachments (f096069)
  • documents: CDA documents and a watchOS-clean build (38df0ea)
  • every payload collects from arrays and reads any numeric type (8086516)
  • example: MVVM demo of every public API with Combine, full authorization and seeding (4b06766)
  • example: watchOS companion app for startWatchApp (5026cc2)
  • health-records: clinical record query, coverage and clinical note types, verifiable records (a413ab6)
  • manager: authorization request status, earliest sample date and estimate recalibration (c39fcee)
  • metadata: hold mixed metadata values and encode them as a flat object (3024a18)
  • observer: hand HealthKit's completion to the observer update handler (cdaefbf)
  • queries: read and observe several types in one query (a14e05e)
  • save and delete several samples at once; consistent error callbacks (faf785b)
  • series: read quantity series values and write quantity and heartbeat series (d0451cc)
  • SPM-only distribution with CI and release-please releases (f4061f1)
  • statistics: deliver statistics collections in batches (b7ee23e)
  • statistics: per-source statistics and data duration (160f958)
  • types: add category types introduced in iOS 18 and 26.2 (da11814)
  • types: add quantity types introduced in iOS 16-18 (4e46b58)
  • types: audiograms, state of mind, GAD-7/PHQ-9 assessments and medications (8807dd2)
  • vision: complete VisionPrescription with lenses, prism, query, writing and per-object authorization (c7c60c3)
  • workouts: activities, statistics, builder-based saving and workout effort (35524cc)

Bug Fixes

  • act on stored samples by uuid and keep payload identity (c2d32a7)
  • authorization accepts CDA documents and adds the types series require (d203faf)
  • category: decode symptom samples with the severity value enum (260a85f)
  • category: replace deprecated audio exposure HealthKit APIs (373651d)
  • category: stop infinite recursion in category value descriptions (62821a6)
  • correlation: keep mixed children and report child conversion errors (f55180b)
  • decorators: correct misspelled workout, ECG and event descriptions (be780a9)
  • decorators: describe unknown HealthKit enum cases instead of crashing (411fdbd)
  • encoding: write non-finite numbers as Infinity, -Infinity and NaN (d541bb2)
  • example: request clinical records separately so authorization works without an Apple Account (3b2097d)
  • payload: skip invalid entries in collect(from:) and reject monitored anchored queries with a limit (7d39927)
  • report invalid authorization types and sample input instead of crashing (f5fc2f3)
  • retriever: serialize concurrent ECG, heartbeat and route results (87c65a9)
  • stop dropping data silently on read and write (b8a9a50)
  • units: read audio exposure in dBASPL and dietary water in mL (d8f66d5)
  • validate units, convert statistics values and always complete writer calls (fdbd2d6)

Reverts

  • payload: keep collect(from:) throwing on invalid entries (32cfaa3)

Code Refactoring

  • stop leaking HealthKit types through the public API (1484c24)