Health 13.0.0 - Refactored Swift Native Code #1208
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Architecture
Core Components
Classes and Their Responsibilities
1. SwiftHealthPlugin
Main plugin class that coordinates all health data operations and serves as the entry point for Flutter method channel calls.
Properties:
healthStore
: HKHealthStore instance for interacting with HealthKitdataTypesDict
: Dictionary mapping string keys to HKSampleType objectsunitDict
: Dictionary mapping string keys to HKUnit objectsworkoutActivityTypeMap
: Dictionary mapping workout activity names to HKWorkoutActivityTypeMethods:
register(with registrar:)
Registers the plugin with Flutter's plugin registrar.
handle(_ call:result:)
Main method channel handler that routes Flutter method calls to appropriate service classes.
Supported Method Calls:
checkIfHealthDataAvailable
requestAuthorization
getData
getIntervalData
getTotalStepsInInterval
writeData
writeAudiogram
writeBloodPressure
writeMeal
writeInsulinDelivery
writeWorkoutData
writeMenstruationFlow
hasPermissions
delete
deleteByUUID
2. HealthDataReader
Handles all read operations from HealthKit.
Methods:
getData(call:result:)
Reads health data for a specific data type within a date range.getIntervalData(call:result:)
Retrieves aggregated health data in specified time intervals.getTotalStepsInInterval(call:result:)
Gets the total step count within a specified time period.3. HealthDataWriter
Handles all write operations to HealthKit.
Methods:
writeData(call:result:)
Writes general health data points.writeAudiogram(call:result:)
Writes audiogram data with frequency and sensitivity measurements.writeBloodPressure(call:result:)
Creates a blood pressure correlation with systolic and diastolic values.writeMeal(call:result:)
Writes nutritional data as a food correlation (iOS 15+).writeWorkoutData(call:result:)
Records workout sessions with activity type, duration, and optional metrics.4. HealthDataOperations
Manages permissions, authorization, and data deletion.
Methods:
hasPermissions(call:result:)
Checks if the app has the required permissions for specified health data types. Permission Types:0
: READ access,1
: WRITE access, Other: READ_WRITE accessrequestAuthorization(call:result:)
Requests authorization from the user for specified health data types.delete(call:result:)
Deletes health data within a specified date range.deleteByUUID(call:result:)
Deletes a specific health record by its UUID.5. HealthUtilities
Provides helper methods for data conversion and sanitization.
Methods:
sanitizeMetadata(_ metadata:)
Converts HealthKit metadata to Flutter-compatible format.dateFromMilliseconds(_ milliseconds:)
Converts milliseconds since epoch to Date object.Error Handling
The plugin uses
PluginError
for internal error handling and returns appropriate Flutter errors:ARGUMENT_ERROR
: Invalid or missing argumentsINVALID_TYPE
: Unknown health data typeHEALTH_ERROR
: HealthKit operation failedWRITE_ERROR
: Failed to write dataPERMISSION_ERROR
: Permission-related errorsDELETE_ERROR
: Failed to delete dataMetadata Handling
The plugin sanitizes HealthKit metadata to ensure Flutter compatibility:
Now all HealthKit operations are asynchronous, results are dispatched to the main thread before calling Flutter callbacks, the plugin handles concurrent operations safely