@kingstinct/react-native-healthkit 12.1.2 → 12.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ios/CategoryTypeModule.swift +49 -97
- package/ios/CharacteristicTypeModule.swift +77 -63
- package/ios/CoreModule.swift +324 -280
- package/ios/CorrelationTypeModule.swift +192 -144
- package/ios/ElectrocardiogramModule.swift +185 -194
- package/ios/HeartbeatSeriesModule.swift +123 -171
- package/ios/Helpers.swift +312 -571
- package/ios/MedicationModule.swift +259 -0
- package/ios/PredicateHelpers.swift +334 -0
- package/ios/QuantityTypeModule.swift +297 -378
- package/ios/Serializers.swift +273 -210
- package/ios/SourceProxy.swift +2 -2
- package/ios/StateOfMindModule.swift +179 -125
- package/ios/WorkoutProxy.swift +235 -112
- package/ios/WorkoutsModule.swift +214 -262
- package/lib/commonjs/healthkit.ios.js +22 -2
- package/lib/commonjs/healthkit.js +35 -5
- package/lib/commonjs/hooks/useStatisticsForQuantity.js +1 -1
- package/lib/commonjs/hooks/useSubscribeToCategorySamples.js +20 -0
- package/lib/commonjs/modules.js +2 -1
- package/lib/commonjs/specs/MedicationModule.nitro.js +27 -0
- package/lib/commonjs/types/Constants.js +2 -1
- package/lib/commonjs/types/QuantityType.js +8 -1
- package/lib/commonjs/types/QueryOptions.js +18 -0
- package/lib/commonjs/types/WeatherCondition.js +32 -32
- package/lib/commonjs/types/Workouts.js +1 -50
- package/lib/commonjs/utils/getCategorySampleById.js +1 -1
- package/lib/commonjs/utils/getQuantitySampleById.js +1 -1
- package/lib/commonjs/utils/getWorkoutById.js +1 -1
- package/lib/commonjs/utils/subscribeToCategorySamples.js +29 -0
- package/lib/commonjs/utils/subscribeToQuantitySamples.js +8 -25
- package/lib/module/healthkit.ios.js +20 -2
- package/lib/module/healthkit.js +32 -2
- package/lib/module/hooks/useStatisticsForQuantity.js +1 -1
- package/lib/module/hooks/useSubscribeToCategorySamples.js +17 -0
- package/lib/module/modules.js +1 -0
- package/lib/module/specs/MedicationModule.nitro.js +26 -0
- package/lib/module/types/Constants.js +1 -0
- package/lib/module/types/QuantityType.js +7 -0
- package/lib/module/types/QueryOptions.js +17 -1
- package/lib/module/types/WeatherCondition.js +31 -31
- package/lib/module/types/Workouts.js +0 -49
- package/lib/module/utils/getCategorySampleById.js +1 -1
- package/lib/module/utils/getQuantitySampleById.js +1 -1
- package/lib/module/utils/getWorkoutById.js +1 -1
- package/lib/module/utils/subscribeToCategorySamples.js +26 -0
- package/lib/module/utils/subscribeToQuantitySamples.js +8 -25
- package/lib/typescript/healthkit.d.ts +18 -9
- package/lib/typescript/healthkit.ios.d.ts +33 -15
- package/lib/typescript/hooks/useSubscribeToCategorySamples.d.ts +3 -0
- package/lib/typescript/modules.d.ts +2 -0
- package/lib/typescript/specs/CategoryTypeModule.nitro.d.ts +2 -2
- package/lib/typescript/specs/CoreModule.nitro.d.ts +2 -1
- package/lib/typescript/specs/CorrelationTypeModule.nitro.d.ts +4 -2
- package/lib/typescript/specs/ElectrocardiogramModule.nitro.d.ts +1 -1
- package/lib/typescript/specs/HeartbeatSeriesModule.nitro.d.ts +1 -1
- package/lib/typescript/specs/MedicationModule.nitro.d.ts +56 -0
- package/lib/typescript/specs/QuantityTypeModule.nitro.d.ts +4 -4
- package/lib/typescript/specs/StateOfMindModule.nitro.d.ts +4 -3
- package/lib/typescript/types/CategoryType.d.ts +10 -20
- package/lib/typescript/types/Constants.d.ts +1 -0
- package/lib/typescript/types/CorrelationType.d.ts +8 -10
- package/lib/typescript/types/ElectrocardiogramSample.d.ts +2 -12
- package/lib/typescript/types/HeartbeatSeries.d.ts +2 -14
- package/lib/typescript/types/QuantitySample.d.ts +2 -8
- package/lib/typescript/types/QuantityType.d.ts +7 -8
- package/lib/typescript/types/QuantityTypeIdentifier.d.ts +23 -23
- package/lib/typescript/types/QueryOptions.d.ts +43 -28
- package/lib/typescript/types/Shared.d.ts +52 -7
- package/lib/typescript/types/StateOfMind.d.ts +7 -10
- package/lib/typescript/types/Subscriptions.d.ts +12 -3
- package/lib/typescript/types/WeatherCondition.d.ts +1 -1
- package/lib/typescript/types/Workouts.d.ts +28 -81
- package/lib/typescript/utils/subscribeToCategorySamples.d.ts +5 -0
- package/nitrogen/generated/ios/ReactNativeHealthkit-Swift-Cxx-Bridge.cpp +57 -0
- package/nitrogen/generated/ios/ReactNativeHealthkit-Swift-Cxx-Bridge.hpp +592 -389
- package/nitrogen/generated/ios/ReactNativeHealthkit-Swift-Cxx-Umbrella.hpp +65 -30
- package/nitrogen/generated/ios/ReactNativeHealthkitAutolinking.mm +8 -0
- package/nitrogen/generated/ios/ReactNativeHealthkitAutolinking.swift +15 -0
- package/nitrogen/generated/ios/c++/HybridCategoryTypeModuleSpecSwift.hpp +32 -26
- package/nitrogen/generated/ios/c++/HybridCoreModuleSpecSwift.hpp +36 -37
- package/nitrogen/generated/ios/c++/HybridCorrelationTypeModuleSpecSwift.hpp +55 -2
- package/nitrogen/generated/ios/c++/HybridElectrocardiogramModuleSpecSwift.hpp +36 -30
- package/nitrogen/generated/ios/c++/HybridHeartbeatSeriesModuleSpecSwift.hpp +35 -29
- package/nitrogen/generated/ios/c++/HybridMedicationModuleSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridMedicationModuleSpecSwift.hpp +181 -0
- package/nitrogen/generated/ios/c++/HybridQuantityTypeModuleSpecSwift.hpp +48 -42
- package/nitrogen/generated/ios/c++/HybridStateOfMindModuleSpecSwift.hpp +59 -36
- package/nitrogen/generated/ios/c++/HybridWorkoutProxySpecSwift.hpp +150 -29
- package/nitrogen/generated/ios/c++/HybridWorkoutsModuleSpecSwift.hpp +13 -28
- package/nitrogen/generated/ios/swift/AggregationStyle.swift +48 -0
- package/nitrogen/generated/ios/swift/CategorySample.swift +571 -24
- package/nitrogen/generated/ios/swift/ComparisonPredicateOperator.swift +2 -2
- package/nitrogen/generated/ios/swift/CorrelationSample.swift +640 -17
- package/nitrogen/generated/ios/swift/{PredicateWithStartAndEnd.swift → DateFilter.swift} +5 -5
- package/nitrogen/generated/ios/swift/ECGQueryOptionsWithAnchor.swift +11 -91
- package/nitrogen/generated/ios/swift/ECGQueryOptionsWithSortOrder.swift +11 -91
- package/nitrogen/generated/ios/swift/ElectrocardiogramSample.swift +570 -72
- package/nitrogen/generated/ios/swift/FilterForSamples.swift +349 -12
- package/nitrogen/generated/ios/swift/FilterForSamplesBase.swift +234 -0
- package/nitrogen/generated/ios/swift/FilterForWorkouts.swift +366 -0
- package/nitrogen/generated/ios/swift/FilterForWorkoutsBase.swift +240 -0
- package/nitrogen/generated/ios/swift/Func_void_MedicationDoseEventsWithAnchorResponse.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_QueryCorrelationSamplesWithAnchorResponse.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_StateOfMindSamplesWithAnchorResponse.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_MedicationDoseEvent_.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_UserAnnotatedMedication_.swift +47 -0
- package/nitrogen/generated/ios/swift/GeneralForm.swift +104 -0
- package/nitrogen/generated/ios/swift/HeartRateMotionContext.swift +44 -0
- package/nitrogen/generated/ios/swift/HeartbeatSeriesSample.swift +565 -37
- package/nitrogen/generated/ios/swift/HybridCategoryTypeModuleSpec.swift +1 -1
- package/nitrogen/generated/ios/swift/HybridCategoryTypeModuleSpec_cxx.swift +2 -2
- package/nitrogen/generated/ios/swift/HybridCoreModuleSpec.swift +2 -1
- package/nitrogen/generated/ios/swift/HybridCoreModuleSpec_cxx.swift +19 -31
- package/nitrogen/generated/ios/swift/HybridCorrelationTypeModuleSpec.swift +2 -1
- package/nitrogen/generated/ios/swift/HybridCorrelationTypeModuleSpec_cxx.swift +21 -2
- package/nitrogen/generated/ios/swift/HybridElectrocardiogramModuleSpec.swift +1 -1
- package/nitrogen/generated/ios/swift/HybridElectrocardiogramModuleSpec_cxx.swift +2 -2
- package/nitrogen/generated/ios/swift/HybridHeartbeatSeriesModuleSpec.swift +1 -1
- package/nitrogen/generated/ios/swift/HybridHeartbeatSeriesModuleSpec_cxx.swift +2 -2
- package/nitrogen/generated/ios/swift/HybridMedicationModuleSpec.swift +60 -0
- package/nitrogen/generated/ios/swift/HybridMedicationModuleSpec_cxx.swift +208 -0
- package/nitrogen/generated/ios/swift/HybridQuantityTypeModuleSpec.swift +2 -2
- package/nitrogen/generated/ios/swift/HybridQuantityTypeModuleSpec_cxx.swift +9 -43
- package/nitrogen/generated/ios/swift/HybridStateOfMindModuleSpec.swift +2 -1
- package/nitrogen/generated/ios/swift/HybridStateOfMindModuleSpec_cxx.swift +21 -2
- package/nitrogen/generated/ios/swift/HybridWorkoutProxySpec.swift +34 -6
- package/nitrogen/generated/ios/swift/HybridWorkoutProxySpec_cxx.swift +376 -36
- package/nitrogen/generated/ios/swift/InsulinDeliveryReason.swift +40 -0
- package/nitrogen/generated/ios/swift/MedicationConcept.swift +80 -0
- package/nitrogen/generated/ios/swift/MedicationDoseEvent.swift +781 -0
- package/nitrogen/generated/ios/swift/MedicationDoseEventLogStatus.swift +56 -0
- package/nitrogen/generated/ios/swift/MedicationDoseEventScheduleType.swift +40 -0
- package/nitrogen/generated/ios/swift/MedicationDoseEventsWithAnchorResponse.swift +81 -0
- package/nitrogen/generated/ios/swift/ObjectTypeIdentifier.swift +16 -16
- package/nitrogen/generated/ios/swift/PredicateWithMetadataKey.swift +7 -7
- package/nitrogen/generated/ios/swift/QuantitySample.swift +574 -27
- package/nitrogen/generated/ios/swift/QuantityTypeIdentifier.swift +16 -16
- package/nitrogen/generated/ios/swift/QueryCorrelationSamplesWithAnchorResponse.swift +81 -0
- package/nitrogen/generated/ios/swift/QueryOptionsWithAnchor.swift +11 -91
- package/nitrogen/generated/ios/swift/QueryOptionsWithAnchorAndUnit.swift +11 -91
- package/nitrogen/generated/ios/swift/QueryOptionsWithSortOrder.swift +11 -91
- package/nitrogen/generated/ios/swift/QueryOptionsWithSortOrderAndUnit.swift +11 -91
- package/nitrogen/generated/ios/swift/RelatedCoding.swift +76 -0
- package/nitrogen/generated/ios/swift/SampleType.swift +68 -0
- package/nitrogen/generated/ios/swift/SampleTypeIdentifier.swift +16 -16
- package/nitrogen/generated/ios/swift/SampleTypeIdentifierWriteable.swift +0 -16
- package/nitrogen/generated/ios/swift/StateOfMindSample.swift +586 -58
- package/nitrogen/generated/ios/swift/StateOfMindSamplesWithAnchorResponse.swift +81 -0
- package/nitrogen/generated/ios/swift/StatisticsQueryOptions.swift +7 -75
- package/nitrogen/generated/ios/swift/UserAnnotatedMedication.swift +87 -0
- package/nitrogen/generated/ios/swift/WeatherCondition.swift +144 -0
- package/nitrogen/generated/ios/swift/WorkoutQueryOptions.swift +11 -105
- package/nitrogen/generated/ios/swift/WorkoutQueryOptionsWithAnchor.swift +11 -105
- package/nitrogen/generated/ios/swift/WorkoutSample.swift +751 -78
- package/nitrogen/generated/shared/c++/AggregationStyle.hpp +64 -0
- package/nitrogen/generated/shared/c++/CategorySample.hpp +126 -23
- package/nitrogen/generated/shared/c++/CorrelationSample.hpp +134 -12
- package/nitrogen/generated/shared/c++/{PredicateWithStartAndEnd.hpp → DateFilter.hpp} +10 -10
- package/nitrogen/generated/shared/c++/ECGQueryOptionsWithAnchor.hpp +12 -31
- package/nitrogen/generated/shared/c++/ECGQueryOptionsWithSortOrder.hpp +12 -31
- package/nitrogen/generated/shared/c++/ElectrocardiogramSample.hpp +135 -36
- package/nitrogen/generated/shared/c++/FilterForSamples.hpp +124 -0
- package/nitrogen/generated/shared/c++/FilterForSamplesBase.hpp +109 -0
- package/nitrogen/generated/shared/c++/FilterForWorkouts.hpp +131 -0
- package/nitrogen/generated/shared/c++/FilterForWorkoutsBase.hpp +116 -0
- package/nitrogen/generated/shared/c++/GeneralForm.hpp +140 -0
- package/nitrogen/generated/shared/c++/HeartRateMotionContext.hpp +67 -0
- package/nitrogen/generated/shared/c++/HeartbeatSeriesSample.hpp +131 -28
- package/nitrogen/generated/shared/c++/HybridCategoryTypeModuleSpec.hpp +1 -2
- package/nitrogen/generated/shared/c++/HybridCoreModuleSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridCoreModuleSpec.hpp +10 -28
- package/nitrogen/generated/shared/c++/HybridCorrelationTypeModuleSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridCorrelationTypeModuleSpec.hpp +11 -1
- package/nitrogen/generated/shared/c++/HybridElectrocardiogramModuleSpec.hpp +1 -2
- package/nitrogen/generated/shared/c++/HybridHeartbeatSeriesModuleSpec.hpp +1 -2
- package/nitrogen/generated/shared/c++/HybridMedicationModuleSpec.cpp +24 -0
- package/nitrogen/generated/shared/c++/HybridMedicationModuleSpec.hpp +80 -0
- package/nitrogen/generated/shared/c++/HybridQuantityTypeModuleSpec.cpp +1 -1
- package/nitrogen/generated/shared/c++/HybridQuantityTypeModuleSpec.hpp +6 -25
- package/nitrogen/generated/shared/c++/HybridStateOfMindModuleSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridStateOfMindModuleSpec.hpp +9 -2
- package/nitrogen/generated/shared/c++/HybridWorkoutProxySpec.cpp +33 -5
- package/nitrogen/generated/shared/c++/HybridWorkoutProxySpec.hpp +56 -16
- package/nitrogen/generated/shared/c++/InsulinDeliveryReason.hpp +62 -0
- package/nitrogen/generated/shared/c++/MedicationConcept.hpp +93 -0
- package/nitrogen/generated/shared/c++/MedicationDoseEvent.hpp +240 -0
- package/nitrogen/generated/shared/c++/MedicationDoseEventLogStatus.hpp +66 -0
- package/nitrogen/generated/shared/c++/MedicationDoseEventScheduleType.hpp +62 -0
- package/nitrogen/generated/shared/c++/MedicationDoseEventsWithAnchorResponse.hpp +89 -0
- package/nitrogen/generated/shared/c++/ObjectTypeIdentifier.hpp +105 -105
- package/nitrogen/generated/shared/c++/PredicateWithMetadataKey.hpp +8 -8
- package/nitrogen/generated/shared/c++/QuantitySample.hpp +130 -27
- package/nitrogen/generated/shared/c++/QuantityTypeIdentifier.hpp +105 -105
- package/nitrogen/generated/shared/c++/QueryCorrelationSamplesWithAnchorResponse.hpp +89 -0
- package/nitrogen/generated/shared/c++/QueryOptionsWithAnchor.hpp +12 -31
- package/nitrogen/generated/shared/c++/QueryOptionsWithAnchorAndUnit.hpp +12 -31
- package/nitrogen/generated/shared/c++/QueryOptionsWithSortOrder.hpp +12 -31
- package/nitrogen/generated/shared/c++/QueryOptionsWithSortOrderAndUnit.hpp +12 -31
- package/nitrogen/generated/shared/c++/RelatedCoding.hpp +84 -0
- package/nitrogen/generated/shared/c++/SampleType.hpp +87 -0
- package/nitrogen/generated/shared/c++/SampleTypeIdentifier.hpp +105 -105
- package/nitrogen/generated/shared/c++/SampleTypeIdentifierWriteable.hpp +105 -121
- package/nitrogen/generated/shared/c++/StateOfMindSample.hpp +139 -36
- package/nitrogen/generated/shared/c++/StateOfMindSamplesWithAnchorResponse.hpp +89 -0
- package/nitrogen/generated/shared/c++/StatisticsQueryOptions.hpp +8 -27
- package/nitrogen/generated/shared/c++/UserAnnotatedMedication.hpp +90 -0
- package/nitrogen/generated/shared/c++/WeatherCondition.hpp +88 -0
- package/nitrogen/generated/shared/c++/WorkoutQueryOptions.hpp +12 -37
- package/nitrogen/generated/shared/c++/WorkoutQueryOptionsWithAnchor.hpp +12 -37
- package/nitrogen/generated/shared/c++/WorkoutSample.hpp +159 -35
- package/package.json +1 -1
- package/src/healthkit.ios.ts +30 -0
- package/src/healthkit.ts +68 -3
- package/src/hooks/useStatisticsForQuantity.ts +1 -1
- package/src/hooks/useSubscribeToCategorySamples.ts +31 -0
- package/src/modules.ts +4 -0
- package/src/specs/CategoryTypeModule.nitro.ts +2 -2
- package/src/specs/CoreModule.nitro.ts +3 -0
- package/src/specs/CorrelationTypeModule.nitro.ts +11 -3
- package/src/specs/ElectrocardiogramModule.nitro.ts +1 -1
- package/src/specs/HeartbeatSeriesModule.nitro.ts +1 -1
- package/src/specs/MedicationModule.nitro.ts +140 -0
- package/src/specs/QuantityTypeModule.nitro.ts +4 -7
- package/src/specs/StateOfMindModule.nitro.ts +10 -2
- package/src/types/CategoryType.ts +15 -22
- package/src/types/Constants.ts +3 -0
- package/src/types/CorrelationType.ts +10 -15
- package/src/types/ElectrocardiogramSample.ts +2 -14
- package/src/types/HeartbeatSeries.ts +2 -15
- package/src/types/QuantitySample.ts +2 -8
- package/src/types/QuantityType.ts +8 -17
- package/src/types/QuantityTypeIdentifier.ts +25 -25
- package/src/types/QueryOptions.ts +54 -43
- package/src/types/Shared.ts +74 -17
- package/src/types/StateOfMind.ts +8 -10
- package/src/types/Subscriptions.ts +19 -3
- package/src/types/WeatherCondition.ts +1 -1
- package/src/types/Workouts.ts +28 -91
- package/src/utils/getCategorySampleById.ts +1 -1
- package/src/utils/getQuantitySampleById.ts +1 -1
- package/src/utils/getWorkoutById.ts +1 -2
- package/src/utils/subscribeToCategorySamples.ts +38 -0
- package/src/utils/subscribeToQuantitySamples.ts +12 -37
- package/nitrogen/generated/ios/swift/FilterForSamplesAnd.swift +0 -94
- package/nitrogen/generated/ios/swift/FilterForSamplesOr.swift +0 -94
- package/nitrogen/generated/ios/swift/PredicateForSamples.swift +0 -21
- package/nitrogen/generated/ios/swift/PredicateForWorkouts.swift +0 -23
- package/nitrogen/generated/ios/swift/PredicateForWorkoutsAnd.swift +0 -108
- package/nitrogen/generated/ios/swift/PredicateForWorkoutsOr.swift +0 -108
- package/nitrogen/generated/ios/swift/PredicateFromWorkout.swift +0 -45
- package/nitrogen/generated/ios/swift/PredicateWithMetadataOperator.swift +0 -48
- package/nitrogen/generated/ios/swift/PredicateWithUUID.swift +0 -35
- package/nitrogen/generated/ios/swift/PredicateWithUUIDs.swift +0 -47
- package/nitrogen/generated/ios/swift/Variant_PredicateWithUUID_PredicateWithUUIDs_PredicateWithMetadataKey_PredicateWithStartAndEnd_PredicateFromWorkout_FilterForSamplesAnd_FilterForSamplesOr.swift +0 -23
- package/nitrogen/generated/ios/swift/Variant_PredicateWithUUID_PredicateWithUUIDs_PredicateWithMetadataKey_PredicateWithStartAndEnd_PredicateFromWorkout_WorkoutActivityTypePredicate_WorkoutDurationPredicate_PredicateForWorkoutsOr_PredicateForWorkoutsAnd.swift +0 -25
- package/nitrogen/generated/ios/swift/WorkoutActivityTypePredicate.swift +0 -35
- package/nitrogen/generated/shared/c++/FilterForSamplesAnd.hpp +0 -90
- package/nitrogen/generated/shared/c++/FilterForSamplesOr.hpp +0 -90
- package/nitrogen/generated/shared/c++/PredicateForWorkoutsAnd.hpp +0 -96
- package/nitrogen/generated/shared/c++/PredicateForWorkoutsOr.hpp +0 -96
- package/nitrogen/generated/shared/c++/PredicateFromWorkout.hpp +0 -77
- package/nitrogen/generated/shared/c++/PredicateWithMetadataOperator.hpp +0 -84
- package/nitrogen/generated/shared/c++/PredicateWithUUID.hpp +0 -75
- package/nitrogen/generated/shared/c++/PredicateWithUUIDs.hpp +0 -76
- package/nitrogen/generated/shared/c++/WorkoutActivityTypePredicate.hpp +0 -76
|
@@ -1,61 +1,13 @@
|
|
|
1
1
|
import HealthKit
|
|
2
2
|
import NitroModules
|
|
3
3
|
|
|
4
|
-
func queryQuantitySamplesInternal(
|
|
5
|
-
typeIdentifier: QuantityTypeIdentifier,
|
|
6
|
-
options: QueryOptionsWithSortOrderAndUnit?
|
|
7
|
-
) throws -> Promise<[QuantitySample]> {
|
|
8
|
-
let quantityType = try initializeQuantityType(typeIdentifier.stringValue)
|
|
9
|
-
let predicate = try createPredicate(filter: options?.filter)
|
|
10
|
-
let limit = getQueryLimit(options?.limit)
|
|
11
|
-
|
|
12
|
-
return Promise.async {
|
|
13
|
-
let unit = try await getUnitToUse(unitOverride: options?.unit, quantityType: quantityType)
|
|
14
|
-
return try await withCheckedThrowingContinuation { continuation in
|
|
15
|
-
let q = HKSampleQuery(
|
|
16
|
-
sampleType: quantityType,
|
|
17
|
-
predicate: predicate,
|
|
18
|
-
limit: limit,
|
|
19
|
-
sortDescriptors: getSortDescriptors(ascending: options?.ascending)
|
|
20
|
-
) { (_: HKSampleQuery, samples: [HKSample]?, error: Error?) in
|
|
21
|
-
guard let err = error else {
|
|
22
|
-
if let returnValue = samples?.compactMap({ sample in
|
|
23
|
-
if let sample = sample as? HKQuantitySample {
|
|
24
|
-
do {
|
|
25
|
-
let serialized = try serializeQuantitySample(
|
|
26
|
-
sample: sample,
|
|
27
|
-
unit: unit
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
return serialized
|
|
31
|
-
} catch {
|
|
32
|
-
print(error.localizedDescription)
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return nil
|
|
37
|
-
}) {
|
|
38
|
-
return continuation.resume(returning: returnValue)
|
|
39
|
-
}
|
|
40
|
-
return continuation.resume(throwing: RuntimeError.error(withMessage: "Empty response returned")
|
|
41
|
-
)
|
|
42
|
-
}
|
|
43
|
-
return continuation.resume(throwing: err)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
store.execute(q)
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
4
|
func emptyStatisticsResponse(from: Date, to: Date) -> QueryStatisticsResponse {
|
|
53
|
-
|
|
5
|
+
var response = QueryStatisticsResponse()
|
|
54
6
|
|
|
55
|
-
|
|
56
|
-
|
|
7
|
+
response.startDate = from
|
|
8
|
+
response.endDate = to
|
|
57
9
|
|
|
58
|
-
|
|
10
|
+
return response
|
|
59
11
|
}
|
|
60
12
|
|
|
61
13
|
func serializeStatistics(gottenStats: HKStatistics, unit: HKUnit) -> QueryStatisticsResponse {
|
|
@@ -65,148 +17,110 @@ func serializeStatistics(gottenStats: HKStatistics, unit: HKUnit) -> QueryStatis
|
|
|
65
17
|
response.endDate = gottenStats.endDate
|
|
66
18
|
|
|
67
19
|
if let averageQuantity = gottenStats.averageQuantity() {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
20
|
+
response.averageQuantity = Quantity(
|
|
21
|
+
unit: unit.unitString,
|
|
22
|
+
quantity: averageQuantity.doubleValue(for: unit)
|
|
23
|
+
)
|
|
72
24
|
}
|
|
73
25
|
if let maximumQuantity = gottenStats.maximumQuantity() {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
26
|
+
response.maximumQuantity = Quantity(
|
|
27
|
+
unit: unit.unitString,
|
|
28
|
+
quantity: maximumQuantity.doubleValue(for: unit)
|
|
29
|
+
)
|
|
78
30
|
}
|
|
79
31
|
if let minimumQuantity = gottenStats.minimumQuantity() {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
32
|
+
response.minimumQuantity = Quantity(
|
|
33
|
+
unit: unit.unitString,
|
|
34
|
+
quantity: minimumQuantity.doubleValue(for: unit)
|
|
35
|
+
)
|
|
84
36
|
}
|
|
85
37
|
if let sumQuantity = gottenStats.sumQuantity() {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
38
|
+
response.sumQuantity = Quantity(
|
|
39
|
+
unit: unit.unitString,
|
|
40
|
+
quantity: sumQuantity.doubleValue(for: unit)
|
|
41
|
+
)
|
|
90
42
|
}
|
|
91
43
|
|
|
92
44
|
if #available(iOS 12, *) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
45
|
+
if let mostRecent = gottenStats.mostRecentQuantity() {
|
|
46
|
+
response.mostRecentQuantity = Quantity(
|
|
47
|
+
unit: unit.unitString,
|
|
48
|
+
quantity: mostRecent.doubleValue(for: unit)
|
|
49
|
+
)
|
|
50
|
+
}
|
|
99
51
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
52
|
+
if let mostRecentDateInterval = gottenStats.mostRecentQuantityDateInterval() {
|
|
53
|
+
response.mostRecentQuantityDateInterval = QuantityDateInterval(
|
|
54
|
+
from: mostRecentDateInterval.start,
|
|
55
|
+
to: mostRecentDateInterval.end
|
|
56
|
+
)
|
|
57
|
+
}
|
|
106
58
|
}
|
|
107
59
|
|
|
108
60
|
if #available(iOS 13, *) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
61
|
+
if let duration = gottenStats.duration() {
|
|
62
|
+
let durationUnit = HKUnit.second()
|
|
63
|
+
response.duration = Quantity(
|
|
64
|
+
unit: durationUnit.unitString,
|
|
65
|
+
quantity: duration.doubleValue(for: durationUnit)
|
|
66
|
+
)
|
|
67
|
+
}
|
|
116
68
|
}
|
|
117
69
|
|
|
118
70
|
return response
|
|
119
71
|
}
|
|
120
72
|
|
|
121
|
-
func saveQuantitySampleInternal(
|
|
122
|
-
typeIdentifier: HKQuantityType,
|
|
123
|
-
unitString: String,
|
|
124
|
-
value: Double,
|
|
125
|
-
start: Date,
|
|
126
|
-
end: Date,
|
|
127
|
-
metadata: [String: Any]?
|
|
128
|
-
) -> Promise<Bool> {
|
|
129
|
-
let unit = HKUnit.init(from: unitString)
|
|
130
|
-
let quantity = HKQuantity.init(unit: unit, doubleValue: value)
|
|
131
|
-
let sample = HKQuantitySample.init(
|
|
132
|
-
type: typeIdentifier,
|
|
133
|
-
quantity: quantity,
|
|
134
|
-
start: start,
|
|
135
|
-
end: end,
|
|
136
|
-
metadata: metadata
|
|
137
|
-
)
|
|
138
|
-
|
|
139
|
-
return Promise.async {
|
|
140
|
-
return try await withCheckedThrowingContinuation { continuation in
|
|
141
|
-
store.save(sample) { (success: Bool, error: Error?) in
|
|
142
|
-
if let error = error {
|
|
143
|
-
return continuation.resume(throwing: error)
|
|
144
|
-
}
|
|
145
|
-
return continuation.resume(returning: success)
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
73
|
func getAnyMapValue(_ anyMap: AnyMap, key: String) -> Any? {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
return nil
|
|
172
|
-
}
|
|
74
|
+
if anyMap.isBool(key: key) {
|
|
75
|
+
return anyMap.getBoolean(key: key)
|
|
76
|
+
}
|
|
77
|
+
if anyMap.isArray(key: key) {
|
|
78
|
+
return anyMap.getArray(key: key)
|
|
79
|
+
}
|
|
80
|
+
if anyMap.isDouble(key: key) {
|
|
81
|
+
return anyMap.getDouble(key: key)
|
|
82
|
+
}
|
|
83
|
+
if anyMap.isObject(key: key) {
|
|
84
|
+
return anyMap.getObject(key: key)
|
|
85
|
+
}
|
|
86
|
+
if anyMap.isString(key: key) {
|
|
87
|
+
return anyMap.getString(key: key)
|
|
88
|
+
}
|
|
89
|
+
if anyMap.isBigInt(key: key) {
|
|
90
|
+
return anyMap.getBigInt(key: key)
|
|
91
|
+
}
|
|
92
|
+
if anyMap.isNull(key: key) {
|
|
173
93
|
return nil
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
func anyMapToDictionary(_ anyMap: AnyMap) -> [String: Any] {
|
|
177
|
-
var dict = [String: Any]()
|
|
178
|
-
anyMap.getAllKeys().forEach { key in
|
|
179
|
-
dict[key] = getAnyMapValue(anyMap, key: key)
|
|
180
|
-
}
|
|
181
|
-
return dict
|
|
94
|
+
}
|
|
95
|
+
return nil
|
|
182
96
|
}
|
|
183
97
|
|
|
184
98
|
func buildStatisticsOptions(statistics: [StatisticsOptions]) -> HKStatisticsOptions {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
}
|
|
197
|
-
if #available(iOS 13, *) {
|
|
198
|
-
if statistic == .duration {
|
|
199
|
-
opts.insert(HKStatisticsOptions.duration)
|
|
200
|
-
}
|
|
201
|
-
if statistic == .mostrecent {
|
|
202
|
-
opts.insert(HKStatisticsOptions.mostRecent)
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
if statistic == .separatebysource {
|
|
206
|
-
opts.insert(HKStatisticsOptions.separateBySource)
|
|
207
|
-
}
|
|
99
|
+
// Build statistics options
|
|
100
|
+
var opts = HKStatisticsOptions()
|
|
101
|
+
for statistic in statistics {
|
|
102
|
+
if statistic == .cumulativesum {
|
|
103
|
+
opts.insert(HKStatisticsOptions.cumulativeSum)
|
|
104
|
+
} else if statistic == .discreteaverage {
|
|
105
|
+
opts.insert(HKStatisticsOptions.discreteAverage)
|
|
106
|
+
} else if statistic == .discretemax {
|
|
107
|
+
opts.insert(HKStatisticsOptions.discreteMax)
|
|
108
|
+
} else if statistic == .discretemin {
|
|
109
|
+
opts.insert(HKStatisticsOptions.discreteMin)
|
|
208
110
|
}
|
|
209
|
-
|
|
111
|
+
if #available(iOS 13, *) {
|
|
112
|
+
if statistic == .duration {
|
|
113
|
+
opts.insert(HKStatisticsOptions.duration)
|
|
114
|
+
}
|
|
115
|
+
if statistic == .mostrecent {
|
|
116
|
+
opts.insert(HKStatisticsOptions.mostRecent)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if statistic == .separatebysource {
|
|
120
|
+
opts.insert(HKStatisticsOptions.separateBySource)
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return opts
|
|
210
124
|
}
|
|
211
125
|
|
|
212
126
|
/// Handles HealthKit's `errorNoData` by resuming the continuation with a fallback value if provided,
|
|
@@ -216,241 +130,246 @@ func buildStatisticsOptions(statistics: [StatisticsOptions]) -> HKStatisticsOpti
|
|
|
216
130
|
/// - continuation: The continuation to resume.
|
|
217
131
|
/// - noDataFallback: Optional closure producing a fallback value to use when the error is `errorNoData`.
|
|
218
132
|
func handleHKNoDataOrThrow<T>(
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
133
|
+
error: Error,
|
|
134
|
+
continuation: CheckedContinuation<T, Error>,
|
|
135
|
+
noDataFallback: (() -> T)
|
|
222
136
|
) {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
137
|
+
let nsError = error as NSError
|
|
138
|
+
if nsError.domain == HKError.errorDomain,
|
|
139
|
+
nsError.code == HKError.Code.errorNoData.rawValue {
|
|
140
|
+
continuation.resume(returning: noDataFallback())
|
|
141
|
+
} else {
|
|
142
|
+
continuation.resume(throwing: error)
|
|
143
|
+
}
|
|
230
144
|
}
|
|
231
145
|
|
|
232
146
|
class QuantityTypeModule: HybridQuantityTypeModuleSpec {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
let samplePredicate = try createPredicateForSamples(filter: filter)
|
|
236
|
-
|
|
237
|
-
return Promise.async {
|
|
238
|
-
return try await withCheckedThrowingContinuation { continuation in
|
|
239
|
-
store.deleteObjects(of: sampleType, predicate: samplePredicate) { (success: Bool, _: Int, error: Error?) in
|
|
240
|
-
if let error = error {
|
|
241
|
-
continuation.resume(throwing: error)
|
|
242
|
-
} else {
|
|
243
|
-
continuation.resume(returning: success)
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
}
|
|
147
|
+
func aggregationStyle(identifier: QuantityTypeIdentifier) throws -> AggregationStyle {
|
|
148
|
+
let sampleType = try initializeQuantityType(identifier.stringValue)
|
|
248
149
|
|
|
150
|
+
if let aggregationStyle = AggregationStyle(
|
|
151
|
+
rawValue: Int32(sampleType.aggregationStyle.rawValue)) {
|
|
152
|
+
return aggregationStyle
|
|
249
153
|
}
|
|
250
154
|
|
|
251
|
-
|
|
252
|
-
|
|
155
|
+
throw runtimeErrorWithPrefix(
|
|
156
|
+
"Got unknown aggregation style value: \(sampleType.aggregationStyle.rawValue)")
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
func isQuantityCompatibleWithUnit(identifier: QuantityTypeIdentifier, unit: String) throws -> Bool {
|
|
160
|
+
let sampleType = try initializeQuantityType(identifier.stringValue)
|
|
253
161
|
|
|
254
|
-
|
|
255
|
-
|
|
162
|
+
return sampleType.is(compatibleWith: HKUnit.init(from: unit))
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
func queryStatisticsForQuantity(
|
|
166
|
+
identifier: QuantityTypeIdentifier, statistics: [StatisticsOptions],
|
|
167
|
+
options: StatisticsQueryOptions?
|
|
168
|
+
) -> Promise<QueryStatisticsResponse> {
|
|
169
|
+
return Promise.async {
|
|
170
|
+
let quantityType = try initializeQuantityType(identifier.stringValue)
|
|
171
|
+
let predicate = createPredicateForSamples(options?.filter)
|
|
172
|
+
let unit = try await getUnitToUse(unitOverride: options?.unit, quantityType: quantityType)
|
|
173
|
+
return try await withCheckedThrowingContinuation { continuation in
|
|
174
|
+
let query = HKStatisticsQuery.init(
|
|
175
|
+
quantityType: quantityType,
|
|
176
|
+
quantitySamplePredicate: predicate,
|
|
177
|
+
options: buildStatisticsOptions(statistics: statistics)
|
|
178
|
+
) { (_, stats: HKStatistics?, error: Error?) in
|
|
179
|
+
DispatchQueue.main.async {
|
|
180
|
+
if let error = error {
|
|
181
|
+
return handleHKNoDataOrThrow(error: error, continuation: continuation) {
|
|
182
|
+
QueryStatisticsResponse()
|
|
183
|
+
}
|
|
184
|
+
}
|
|
256
185
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
let predicate = try createPredicate(filter: options?.filter)
|
|
261
|
-
|
|
262
|
-
return Promise.async {
|
|
263
|
-
let unit = try await getUnitToUse(unitOverride: options?.unit, quantityType: quantityType)
|
|
264
|
-
return try await withCheckedThrowingContinuation { continuation in
|
|
265
|
-
let query = HKStatisticsQuery.init(
|
|
266
|
-
quantityType: quantityType,
|
|
267
|
-
quantitySamplePredicate: predicate,
|
|
268
|
-
options: buildStatisticsOptions(statistics: statistics)
|
|
269
|
-
) { (_, stats: HKStatistics?, error: Error?) in
|
|
270
|
-
DispatchQueue.main.async {
|
|
271
|
-
if let error = error {
|
|
272
|
-
return handleHKNoDataOrThrow(error: error, continuation: continuation) {
|
|
273
|
-
QueryStatisticsResponse()
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
guard let gottenStats = stats else {
|
|
278
|
-
let emptyResponse = QueryStatisticsResponse()
|
|
279
|
-
return continuation.resume(returning: emptyResponse)
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
let response = serializeStatistics(gottenStats: gottenStats, unit: unit)
|
|
283
|
-
|
|
284
|
-
continuation.resume(returning: response)
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
store.execute(query)
|
|
186
|
+
guard let gottenStats = stats else {
|
|
187
|
+
let emptyResponse = QueryStatisticsResponse()
|
|
188
|
+
return continuation.resume(returning: emptyResponse)
|
|
289
189
|
}
|
|
190
|
+
|
|
191
|
+
let response = serializeStatistics(gottenStats: gottenStats, unit: unit)
|
|
192
|
+
|
|
193
|
+
continuation.resume(returning: response)
|
|
194
|
+
}
|
|
290
195
|
}
|
|
196
|
+
|
|
197
|
+
store.execute(query)
|
|
198
|
+
}
|
|
291
199
|
}
|
|
200
|
+
}
|
|
292
201
|
|
|
293
|
-
|
|
294
|
-
|
|
202
|
+
func queryStatisticsCollectionForQuantity(
|
|
203
|
+
identifier: QuantityTypeIdentifier, statistics: [StatisticsOptions], anchorDate: Date,
|
|
204
|
+
intervalComponents: IntervalComponents, options: StatisticsQueryOptions?
|
|
205
|
+
) -> Promise<[QueryStatisticsResponse]> {
|
|
206
|
+
return Promise.async {
|
|
207
|
+
let quantityType = try initializeQuantityType(identifier.stringValue)
|
|
295
208
|
|
|
296
|
-
|
|
209
|
+
let predicate = createPredicateForSamples(options?.filter)
|
|
297
210
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
211
|
+
// Create date components from interval
|
|
212
|
+
var dateComponents = DateComponents()
|
|
213
|
+
if let minute = intervalComponents.minute {
|
|
214
|
+
dateComponents.minute = Int(minute)
|
|
215
|
+
}
|
|
216
|
+
if let hour = intervalComponents.hour {
|
|
217
|
+
dateComponents.hour = Int(hour)
|
|
218
|
+
}
|
|
219
|
+
if let day = intervalComponents.day {
|
|
220
|
+
dateComponents.day = Int(day)
|
|
221
|
+
}
|
|
222
|
+
if let month = intervalComponents.month {
|
|
223
|
+
dateComponents.month = Int(month)
|
|
224
|
+
}
|
|
225
|
+
if let year = intervalComponents.year {
|
|
226
|
+
dateComponents.year = Int(year)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Build statistics options
|
|
230
|
+
let opts = buildStatisticsOptions(statistics: statistics)
|
|
231
|
+
|
|
232
|
+
let unit = try await getUnitToUse(unitOverride: options?.unit, quantityType: quantityType)
|
|
233
|
+
|
|
234
|
+
return try await withCheckedThrowingContinuation { continuation in
|
|
235
|
+
let query = HKStatisticsCollectionQuery.init(
|
|
236
|
+
quantityType: quantityType,
|
|
237
|
+
quantitySamplePredicate: predicate,
|
|
238
|
+
options: opts,
|
|
239
|
+
anchorDate: anchorDate,
|
|
240
|
+
intervalComponents: dateComponents
|
|
241
|
+
)
|
|
315
242
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
let unit = try await getUnitToUse(unitOverride: options?.unit, quantityType: quantityType)
|
|
321
|
-
|
|
322
|
-
return try await withCheckedThrowingContinuation { continuation in
|
|
323
|
-
let query = HKStatisticsCollectionQuery.init(
|
|
324
|
-
quantityType: quantityType,
|
|
325
|
-
quantitySamplePredicate: predicate,
|
|
326
|
-
options: opts,
|
|
327
|
-
anchorDate: anchorDate,
|
|
328
|
-
intervalComponents: dateComponents
|
|
329
|
-
)
|
|
330
|
-
|
|
331
|
-
query.initialResultsHandler = { (_, results: HKStatisticsCollection?, error: Error?) in
|
|
332
|
-
if let error = error {
|
|
333
|
-
return handleHKNoDataOrThrow(error: error, continuation: continuation) {
|
|
334
|
-
[]
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
guard let statistics = results else {
|
|
339
|
-
continuation.resume(returning: [])
|
|
340
|
-
return
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
var responseArray: [QueryStatisticsResponse] = []
|
|
344
|
-
|
|
345
|
-
// Limit enumeration to the range in the provided filter if possible
|
|
346
|
-
var enumerateFrom = Date.distantPast
|
|
347
|
-
var enumerateTo = Date()
|
|
348
|
-
|
|
349
|
-
if let filter = options?.filter {
|
|
350
|
-
switch filter {
|
|
351
|
-
case .fourth(let dateFilter):
|
|
352
|
-
enumerateFrom = dateFilter.startDate ?? enumerateFrom
|
|
353
|
-
enumerateTo = dateFilter.endDate ?? enumerateTo
|
|
354
|
-
default:
|
|
355
|
-
break
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
statistics.enumerateStatistics(from: enumerateFrom, to: enumerateTo) { stats, _ in
|
|
360
|
-
var response = serializeStatistics(gottenStats: stats, unit: unit)
|
|
361
|
-
|
|
362
|
-
responseArray.append(response)
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
continuation.resume(returning: responseArray)
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
store.execute(query)
|
|
243
|
+
query.initialResultsHandler = { (_, results: HKStatisticsCollection?, error: Error?) in
|
|
244
|
+
if let error = error {
|
|
245
|
+
return handleHKNoDataOrThrow(error: error, continuation: continuation) {
|
|
246
|
+
[]
|
|
369
247
|
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
guard let statistics = results else {
|
|
251
|
+
continuation.resume(returning: [])
|
|
252
|
+
return
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
var responseArray: [QueryStatisticsResponse] = []
|
|
256
|
+
|
|
257
|
+
// Limit enumeration to the range in the provided filter if possible
|
|
258
|
+
var enumerateFrom = Date.distantPast
|
|
259
|
+
var enumerateTo = Date()
|
|
260
|
+
|
|
261
|
+
if let filter = options?.filter {
|
|
262
|
+
enumerateFrom = filter.date?.startDate ?? enumerateFrom
|
|
263
|
+
enumerateTo = filter.date?.endDate ?? enumerateTo
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
statistics.enumerateStatistics(from: enumerateFrom, to: enumerateTo) { stats, _ in
|
|
267
|
+
let response = serializeStatistics(gottenStats: stats, unit: unit)
|
|
268
|
+
|
|
269
|
+
responseArray.append(response)
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
continuation.resume(returning: responseArray)
|
|
370
273
|
}
|
|
274
|
+
|
|
275
|
+
store.execute(query)
|
|
276
|
+
}
|
|
371
277
|
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
func queryQuantitySamplesWithAnchor(
|
|
281
|
+
identifier: QuantityTypeIdentifier, options: QueryOptionsWithAnchorAndUnit
|
|
282
|
+
) -> Promise<QuantitySamplesWithAnchorResponse> {
|
|
283
|
+
return Promise.async {
|
|
284
|
+
let quantityType = try initializeQuantityType(identifier.stringValue)
|
|
285
|
+
let predicate = createPredicateForSamples(options.filter)
|
|
372
286
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
let actualAnchor = try deserializeHKQueryAnchor(base64String: options.anchor)
|
|
287
|
+
let unit = try await getUnitToUse(
|
|
288
|
+
unitOverride: options.unit,
|
|
289
|
+
quantityType: quantityType
|
|
290
|
+
)
|
|
378
291
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
292
|
+
let response = try await sampleAnchoredQueryAsync(
|
|
293
|
+
sampleType: quantityType,
|
|
294
|
+
limit: options.limit,
|
|
295
|
+
queryAnchor: options.anchor,
|
|
296
|
+
predicate: predicate
|
|
297
|
+
)
|
|
384
298
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
newAnchor: HKQueryAnchor?,
|
|
396
|
-
error: Error?
|
|
397
|
-
) in
|
|
398
|
-
if let error = error {
|
|
399
|
-
return handleHKNoDataOrThrow(error: error, continuation: continuation) {
|
|
400
|
-
QuantitySamplesWithAnchorResponse(
|
|
401
|
-
samples: [],
|
|
402
|
-
deletedSamples: [],
|
|
403
|
-
newAnchor: ""
|
|
404
|
-
)
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
let deletedSamples = deletedSamples?.map { serializeDeletedSample(sample: $0) } ?? []
|
|
409
|
-
let newAnchor = serializeAnchor(anchor: newAnchor) ?? ""
|
|
410
|
-
|
|
411
|
-
let quantitySamples = samples?.compactMap { sample in
|
|
412
|
-
if let quantitySample = sample as? HKQuantitySample {
|
|
413
|
-
do {
|
|
414
|
-
return try serializeQuantitySample(
|
|
415
|
-
sample: quantitySample,
|
|
416
|
-
unit: unit
|
|
417
|
-
)
|
|
418
|
-
} catch {
|
|
419
|
-
print(error.localizedDescription)
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
return nil
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
let response = QuantitySamplesWithAnchorResponse(
|
|
426
|
-
samples: quantitySamples ?? [],
|
|
427
|
-
deletedSamples: deletedSamples,
|
|
428
|
-
newAnchor: newAnchor,
|
|
429
|
-
)
|
|
430
|
-
|
|
431
|
-
continuation.resume(returning: response)
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
store.execute(query)
|
|
435
|
-
}
|
|
299
|
+
let quantitySamples = response.samples.compactMap { sample in
|
|
300
|
+
if let quantitySample = sample as? HKQuantitySample {
|
|
301
|
+
do {
|
|
302
|
+
return try serializeQuantitySample(
|
|
303
|
+
sample: quantitySample,
|
|
304
|
+
unit: unit
|
|
305
|
+
)
|
|
306
|
+
} catch {
|
|
307
|
+
warnWithPrefix("queryQuantitySamplesWithAnchor: \(error.localizedDescription)")
|
|
308
|
+
}
|
|
436
309
|
}
|
|
310
|
+
return nil
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
return QuantitySamplesWithAnchorResponse(
|
|
314
|
+
samples: quantitySamples,
|
|
315
|
+
deletedSamples: response.deletedSamples,
|
|
316
|
+
newAnchor: response.newAnchor
|
|
317
|
+
)
|
|
437
318
|
}
|
|
319
|
+
}
|
|
438
320
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
321
|
+
func saveQuantitySample(
|
|
322
|
+
identifier: QuantityTypeIdentifier, unit: String, value: Double, start: Date, end: Date,
|
|
323
|
+
metadata: AnyMap
|
|
324
|
+
) -> Promise<Bool> {
|
|
325
|
+
return Promise.async {
|
|
326
|
+
let unit = HKUnit.init(from: unit)
|
|
327
|
+
let quantity = HKQuantity.init(unit: unit, doubleValue: value)
|
|
328
|
+
let typeIdentifier = HKQuantityType(
|
|
329
|
+
HKQuantityTypeIdentifier(rawValue: identifier.stringValue)
|
|
330
|
+
)
|
|
331
|
+
let metadata = anyMapToDictionary(metadata)
|
|
332
|
+
|
|
333
|
+
let sample = HKQuantitySample.init(
|
|
334
|
+
type: typeIdentifier,
|
|
335
|
+
quantity: quantity,
|
|
336
|
+
start: start,
|
|
337
|
+
end: end,
|
|
338
|
+
metadata: metadata
|
|
339
|
+
)
|
|
340
|
+
return try await saveAsync(sample: sample)
|
|
450
341
|
}
|
|
342
|
+
}
|
|
451
343
|
|
|
452
|
-
|
|
453
|
-
|
|
344
|
+
func queryQuantitySamples(
|
|
345
|
+
identifier: QuantityTypeIdentifier, options: QueryOptionsWithSortOrderAndUnit
|
|
346
|
+
) -> Promise<[QuantitySample]> {
|
|
347
|
+
return Promise.async {
|
|
348
|
+
let quantityType = try initializeQuantityType(identifier.stringValue)
|
|
349
|
+
let unit = try await getUnitToUse(unitOverride: options.unit, quantityType: quantityType)
|
|
350
|
+
let samples = try await sampleQueryAsync(
|
|
351
|
+
sampleType: quantityType,
|
|
352
|
+
limit: options.limit,
|
|
353
|
+
predicate: createPredicateForSamples(options.filter),
|
|
354
|
+
sortDescriptors: getSortDescriptors(ascending: options.ascending)
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
return samples.compactMap({ sample in
|
|
358
|
+
if let sample = sample as? HKQuantitySample {
|
|
359
|
+
do {
|
|
360
|
+
let serialized = try serializeQuantitySample(
|
|
361
|
+
sample: sample,
|
|
362
|
+
unit: unit
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
return serialized
|
|
366
|
+
} catch {
|
|
367
|
+
warnWithPrefix("Error serializing quantity sample: \(error.localizedDescription)")
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return nil
|
|
371
|
+
})
|
|
454
372
|
}
|
|
373
|
+
}
|
|
455
374
|
|
|
456
375
|
}
|