@kingstinct/react-native-healthkit 14.1.0 → 16.0.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/README.md +37 -3
- package/ReactNativeHealthkit.podspec +11 -7
- package/app.plugin.js +33 -94
- package/app.plugin.ts +29 -104
- package/ios/CategoryTypeModule.swift +1 -0
- package/ios/CharacteristicTypeModule.swift +7 -6
- package/ios/Constants.swift +9 -10
- package/ios/CoreModule.swift +77 -42
- package/ios/CorrelationTypeModule.swift +3 -2
- package/ios/ElectrocardiogramModule.swift +4 -3
- package/ios/HeartbeatSeriesModule.swift +4 -3
- package/ios/Helpers.swift +11 -216
- package/ios/MedicationModule.swift +9 -8
- package/ios/MemoryEstimation.swift +84 -0
- package/ios/PredicateHelpers.swift +16 -86
- package/ios/QuantityTypeModule.swift +37 -28
- package/ios/Serializers.swift +34 -70
- package/ios/SourceProxy.swift +15 -5
- package/ios/StateOfMindModule.swift +3 -2
- package/ios/WorkoutProxy.swift +31 -13
- package/ios/WorkoutsModule.swift +4 -3
- package/lib/commonjs/generated/healthkit.generated.js +15 -3
- package/lib/commonjs/healthkit.ios.js +6 -2
- package/lib/commonjs/healthkit.js +24 -79
- package/lib/commonjs/types/Auth.js +3 -18
- package/lib/commonjs/types/Background.js +2 -10
- package/lib/commonjs/types/QueryOptions.js +2 -17
- package/lib/module/generated/healthkit.generated.js +14 -2
- package/lib/module/healthkit.ios.js +4 -0
- package/lib/module/healthkit.js +22 -77
- package/lib/module/types/Auth.js +1 -18
- package/lib/module/types/Background.js +1 -10
- package/lib/module/types/QueryOptions.js +1 -17
- package/lib/typescript/generated/healthkit.generated.d.ts +20 -7
- package/lib/typescript/healthkit.d.ts +4 -2
- package/lib/typescript/healthkit.ios.d.ts +13 -9
- package/lib/typescript/specs/CoreModule.nitro.d.ts +22 -4
- package/lib/typescript/specs/SourceProxy.nitro.d.ts +2 -5
- package/lib/typescript/types/Auth.d.ts +1 -16
- package/lib/typescript/types/Background.d.ts +1 -9
- package/lib/typescript/types/Device.d.ts +1 -13
- package/lib/typescript/types/QuantityType.d.ts +3 -3
- package/lib/typescript/types/QueryOptions.d.ts +3 -37
- package/lib/typescript/types/Shared.d.ts +2 -25
- package/lib/typescript/types/Source.d.ts +1 -10
- package/lib/typescript/types/Subscriptions.d.ts +2 -3
- package/lib/typescript/types/Units.d.ts +1 -1
- package/nitrogen/generated/ios/ReactNativeHealthkit-Swift-Cxx-Bridge.cpp +24 -16
- package/nitrogen/generated/ios/ReactNativeHealthkit-Swift-Cxx-Bridge.hpp +91 -12
- package/nitrogen/generated/ios/c++/HybridCategoryTypeModuleSpecSwift.hpp +8 -5
- package/nitrogen/generated/ios/c++/HybridCoreModuleSpecSwift.hpp +8 -0
- package/nitrogen/generated/ios/c++/HybridCorrelationTypeModuleSpecSwift.hpp +8 -5
- package/nitrogen/generated/ios/c++/HybridElectrocardiogramModuleSpecSwift.hpp +8 -5
- package/nitrogen/generated/ios/c++/HybridHeartbeatSeriesModuleSpecSwift.hpp +8 -5
- package/nitrogen/generated/ios/c++/HybridMedicationModuleSpecSwift.hpp +8 -5
- package/nitrogen/generated/ios/c++/HybridQuantityTypeModuleSpecSwift.hpp +8 -5
- package/nitrogen/generated/ios/c++/HybridStateOfMindModuleSpecSwift.hpp +8 -5
- package/nitrogen/generated/ios/c++/HybridWorkoutProxySpecSwift.hpp +3 -4
- package/nitrogen/generated/ios/c++/HybridWorkoutsModuleSpecSwift.hpp +6 -3
- package/nitrogen/generated/ios/swift/CategorySample.swift +8 -8
- package/nitrogen/generated/ios/swift/CategoryTypeIdentifier.swift +8 -0
- package/nitrogen/generated/ios/swift/CategoryTypeIdentifierWriteable.swift +8 -0
- package/nitrogen/generated/ios/swift/CorrelationSample.swift +8 -8
- package/nitrogen/generated/ios/swift/ElectrocardiogramSample.swift +8 -8
- package/nitrogen/generated/ios/swift/Func_void_std__unordered_map_std__string__std__chrono__system_clock__time_point_.swift +54 -0
- package/nitrogen/generated/ios/swift/HeartbeatSeriesSample.swift +8 -8
- package/nitrogen/generated/ios/swift/HybridCoreModuleSpec.swift +1 -0
- package/nitrogen/generated/ios/swift/HybridCoreModuleSpec_cxx.swift +25 -0
- package/nitrogen/generated/ios/swift/MedicationDoseEvent.swift +8 -8
- package/nitrogen/generated/ios/swift/ObjectTypeIdentifier.swift +12 -4
- package/nitrogen/generated/ios/swift/QuantitySample.swift +8 -8
- package/nitrogen/generated/ios/swift/QuantityTypeIdentifier.swift +4 -4
- package/nitrogen/generated/ios/swift/QuantityTypeIdentifierWriteable.swift +4 -4
- package/nitrogen/generated/ios/swift/QueryStatisticsResponse.swift +6 -13
- package/nitrogen/generated/ios/swift/QueryStatisticsResponseFromSingleSource.swift +4 -11
- package/nitrogen/generated/ios/swift/SampleTypeIdentifier.swift +12 -4
- package/nitrogen/generated/ios/swift/SampleTypeIdentifierWriteable.swift +12 -4
- package/nitrogen/generated/ios/swift/SourceRevision.swift +4 -11
- package/nitrogen/generated/ios/swift/StateOfMindSample.swift +8 -8
- package/nitrogen/generated/ios/swift/WorkoutActivityType.swift +8 -0
- package/nitrogen/generated/shared/c++/CategorySample.hpp +7 -7
- package/nitrogen/generated/shared/c++/CategoryTypeIdentifier.hpp +67 -59
- package/nitrogen/generated/shared/c++/CategoryTypeIdentifierWriteable.hpp +67 -59
- package/nitrogen/generated/shared/c++/CorrelationSample.hpp +7 -7
- package/nitrogen/generated/shared/c++/ElectrocardiogramSample.hpp +7 -7
- package/nitrogen/generated/shared/c++/HeartbeatSeriesSample.hpp +7 -7
- package/nitrogen/generated/shared/c++/HybridCoreModuleSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridCoreModuleSpec.hpp +3 -1
- package/nitrogen/generated/shared/c++/MedicationDoseEvent.hpp +7 -7
- package/nitrogen/generated/shared/c++/ObjectTypeIdentifier.hpp +206 -198
- package/nitrogen/generated/shared/c++/QuantitySample.hpp +7 -7
- package/nitrogen/generated/shared/c++/QuantityTypeIdentifier.hpp +73 -73
- package/nitrogen/generated/shared/c++/QuantityTypeIdentifierWriteable.hpp +73 -73
- package/nitrogen/generated/shared/c++/QueryStatisticsResponse.hpp +8 -9
- package/nitrogen/generated/shared/c++/QueryStatisticsResponseFromSingleSource.hpp +8 -9
- package/nitrogen/generated/shared/c++/SampleTypeIdentifier.hpp +199 -191
- package/nitrogen/generated/shared/c++/SampleTypeIdentifierWriteable.hpp +193 -185
- package/nitrogen/generated/shared/c++/SourceRevision.hpp +8 -9
- package/nitrogen/generated/shared/c++/StateOfMindSample.hpp +7 -7
- package/nitrogen/generated/shared/c++/WorkoutActivityType.hpp +4 -0
- package/package.json +8 -3
- package/src/generated/healthkit-schema.json +53 -8
- package/src/generated/healthkit.generated.ts +22 -6
- package/src/healthkit.ios.ts +6 -0
- package/src/healthkit.ts +32 -84
- package/src/specs/CoreModule.nitro.ts +25 -4
- package/src/specs/SourceProxy.nitro.ts +2 -4
- package/src/test-setup.ts +1 -0
- package/src/type-tests/generated-typing.ts +30 -8
- package/src/types/Auth.ts +4 -17
- package/src/types/Background.ts +1 -9
- package/src/types/Device.ts +1 -13
- package/src/types/QuantityType.ts +3 -3
- package/src/types/QueryOptions.ts +7 -65
- package/src/types/Shared.ts +7 -28
- package/src/types/Source.ts +1 -11
- package/src/types/Subscriptions.ts +2 -3
- package/src/types/Units.ts +1 -1
- package/ios/BackgroundDeliveryManager.swift +0 -277
- package/ios/Bridge.h +0 -10
- package/ios/ExceptionCatcher.h +0 -5
- package/ios/ExceptionCatcher.mm +0 -32
- package/ios/module.modulemap +0 -5
|
@@ -1,277 +0,0 @@
|
|
|
1
|
-
import Foundation
|
|
2
|
-
import HealthKit
|
|
3
|
-
import os.log
|
|
4
|
-
|
|
5
|
-
private let bgLog = OSLog(subsystem: "com.kingstinct.healthkit", category: "BackgroundDelivery")
|
|
6
|
-
|
|
7
|
-
/// Manages HealthKit background delivery by registering observer queries at app launch,
|
|
8
|
-
/// before the JS bridge is available. This is required by Apple — observer queries must
|
|
9
|
-
/// be set up in `application(_:didFinishLaunchingWithOptions:)` to receive background
|
|
10
|
-
/// delivery callbacks after the app has been terminated.
|
|
11
|
-
///
|
|
12
|
-
/// Usage from AppDelegate.swift:
|
|
13
|
-
/// BackgroundDeliveryManager.shared.setupBackgroundObservers()
|
|
14
|
-
///
|
|
15
|
-
/// The types to observe are persisted in UserDefaults by `configureBackgroundTypes()`
|
|
16
|
-
/// called from JS. On subsequent cold launches, the manager reads these and registers
|
|
17
|
-
/// observers immediately, queuing any events until JS subscribes via `drainPendingEvents()`.
|
|
18
|
-
@objc public class BackgroundDeliveryManager: NSObject {
|
|
19
|
-
@objc public static let shared = BackgroundDeliveryManager()
|
|
20
|
-
|
|
21
|
-
private let healthStore = HKHealthStore()
|
|
22
|
-
private let queue = DispatchQueue(label: "com.kingstinct.healthkit.background", attributes: .concurrent)
|
|
23
|
-
private var observerQueries: [String: HKObserverQuery] = [:]
|
|
24
|
-
private var pendingEvents: [(typeIdentifier: String, errorMessage: String?)] = []
|
|
25
|
-
private var jsCallback: ((String, String?) -> Void)?
|
|
26
|
-
// Per-type callbacks, checked before the global `jsCallback` above. Lets
|
|
27
|
-
// CoreModule.subscribeToObserverQuery route a JS subscription for a
|
|
28
|
-
// background-configured type through this manager's already-running
|
|
29
|
-
// HKObserverQuery instead of registering a second, independent one.
|
|
30
|
-
private var typeCallbacks: [String: (String, String?) -> Void] = [:]
|
|
31
|
-
private var isSetUp = false
|
|
32
|
-
|
|
33
|
-
static let typesKey = "com.kingstinct.healthkit.backgroundTypes"
|
|
34
|
-
static let frequencyKey = "com.kingstinct.healthkit.backgroundFrequency"
|
|
35
|
-
|
|
36
|
-
private override init() {
|
|
37
|
-
super.init()
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/// Call this from AppDelegate.didFinishLaunchingWithOptions to register observer queries
|
|
41
|
-
/// for any previously configured background delivery types.
|
|
42
|
-
@objc public func setupBackgroundObservers() {
|
|
43
|
-
guard HKHealthStore.isHealthDataAvailable() else { return }
|
|
44
|
-
|
|
45
|
-
guard let typeIdentifiers = UserDefaults.standard.stringArray(forKey: BackgroundDeliveryManager.typesKey) else {
|
|
46
|
-
return
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
let frequencyRaw = UserDefaults.standard.integer(forKey: BackgroundDeliveryManager.frequencyKey)
|
|
50
|
-
let frequency = HKUpdateFrequency(rawValue: frequencyRaw) ?? .immediate
|
|
51
|
-
|
|
52
|
-
registerObservers(typeIdentifiers: typeIdentifiers, frequency: frequency)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/// Persist types and frequency, then register observers for the current session.
|
|
56
|
-
/// Called from JS via CoreModule.configureBackgroundTypes().
|
|
57
|
-
func configure(typeIdentifiers: [String], frequency: HKUpdateFrequency) {
|
|
58
|
-
UserDefaults.standard.set(typeIdentifiers, forKey: BackgroundDeliveryManager.typesKey)
|
|
59
|
-
UserDefaults.standard.set(frequency.rawValue, forKey: BackgroundDeliveryManager.frequencyKey)
|
|
60
|
-
|
|
61
|
-
// Tear down existing observers before re-registering
|
|
62
|
-
tearDown()
|
|
63
|
-
registerObservers(typeIdentifiers: typeIdentifiers, frequency: frequency)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/// Subscribe a JS callback. Any events that arrived before JS was ready are flushed immediately.
|
|
67
|
-
func setCallback(_ callback: @escaping (String, String?) -> Void) {
|
|
68
|
-
queue.sync(flags: .barrier) {
|
|
69
|
-
self.jsCallback = callback
|
|
70
|
-
let events = self.pendingEvents
|
|
71
|
-
self.pendingEvents = []
|
|
72
|
-
|
|
73
|
-
for event in events {
|
|
74
|
-
callback(event.typeIdentifier, event.errorMessage)
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/// Remove the JS callback (e.g., on teardown).
|
|
80
|
-
func removeCallback() {
|
|
81
|
-
queue.sync(flags: .barrier) {
|
|
82
|
-
self.jsCallback = nil
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/// Returns any pending events and clears the queue. Used by CoreModule.subscribeToObserverQuery
|
|
87
|
-
/// to flush events that arrived before JS subscribed.
|
|
88
|
-
func drainPendingEvents() -> [(typeIdentifier: String, errorMessage: String?)] {
|
|
89
|
-
return queue.sync(flags: .barrier) {
|
|
90
|
-
let events = self.pendingEvents
|
|
91
|
-
self.pendingEvents = []
|
|
92
|
-
return events
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/// Subscribe a JS callback for a specific type. Any events for this type
|
|
97
|
-
/// that arrived before JS subscribed (e.g. from a background wake, queued
|
|
98
|
-
/// in `pendingEvents` above) are flushed immediately.
|
|
99
|
-
func setCallback(typeIdentifier: String, callback: @escaping (String, String?) -> Void) {
|
|
100
|
-
queue.sync(flags: .barrier) {
|
|
101
|
-
self.typeCallbacks[typeIdentifier] = callback
|
|
102
|
-
let matching = self.pendingEvents.filter { $0.typeIdentifier == typeIdentifier }
|
|
103
|
-
self.pendingEvents.removeAll { $0.typeIdentifier == typeIdentifier }
|
|
104
|
-
for event in matching {
|
|
105
|
-
callback(typeIdentifier, event.errorMessage)
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/// Remove the per-type JS callback (e.g., on unsubscribe).
|
|
111
|
-
func removeCallback(typeIdentifier: String) {
|
|
112
|
-
queue.sync(flags: .barrier) {
|
|
113
|
-
self.typeCallbacks.removeValue(forKey: typeIdentifier)
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/// True if `typeIdentifier` has a native HKObserverQuery registered by
|
|
118
|
-
/// `registerObservers` — i.e. background delivery is configured for it.
|
|
119
|
-
/// CoreModule.subscribeToObserverQuery checks this before deciding whether
|
|
120
|
-
/// to reuse this manager's observer or register its own.
|
|
121
|
-
func isBackgroundConfigured(typeIdentifier: String) -> Bool {
|
|
122
|
-
return queue.sync {
|
|
123
|
-
self.observerQueries[typeIdentifier] != nil
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/// Stop all observer queries and clear state.
|
|
128
|
-
func tearDown() {
|
|
129
|
-
queue.sync(flags: .barrier) {
|
|
130
|
-
for (_, query) in self.observerQueries {
|
|
131
|
-
self.healthStore.stop(query)
|
|
132
|
-
}
|
|
133
|
-
self.observerQueries = [:]
|
|
134
|
-
self.typeCallbacks = [:]
|
|
135
|
-
self.isSetUp = false
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/// Clear persisted configuration (disables background delivery on next launch).
|
|
140
|
-
func clearConfiguration() {
|
|
141
|
-
UserDefaults.standard.removeObject(forKey: BackgroundDeliveryManager.typesKey)
|
|
142
|
-
UserDefaults.standard.removeObject(forKey: BackgroundDeliveryManager.frequencyKey)
|
|
143
|
-
tearDown()
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
private func registerObservers(typeIdentifiers: [String], frequency: HKUpdateFrequency) {
|
|
147
|
-
queue.sync(flags: .barrier) {
|
|
148
|
-
guard !self.isSetUp else { return }
|
|
149
|
-
self.isSetUp = true
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
for typeIdentifier in typeIdentifiers {
|
|
153
|
-
guard let sampleType = sampleTypeFromString(typeIdentifier) else {
|
|
154
|
-
print("[react-native-healthkit] BackgroundDeliveryManager: skipping unrecognized type \(typeIdentifier)")
|
|
155
|
-
continue
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Use nil predicate to catch all samples, including those written while the app was terminated.
|
|
159
|
-
// The current subscribeToObserverQuery uses Date.init() which misses data from when the app was dead.
|
|
160
|
-
let query = HKObserverQuery(
|
|
161
|
-
sampleType: sampleType,
|
|
162
|
-
predicate: nil
|
|
163
|
-
) { [weak self] (_: HKObserverQuery, completionHandler: @escaping HKObserverQueryCompletionHandler, error: Error?) in
|
|
164
|
-
// handleObserverCallback opens a beginBackgroundTask() window as its
|
|
165
|
-
// first, synchronous action, before this returns to call
|
|
166
|
-
// completionHandler() — otherwise iOS is free to suspend the process
|
|
167
|
-
// the moment HealthKit's own completion handler fires, possibly
|
|
168
|
-
// before Hermes has finished booting to run the JS callback.
|
|
169
|
-
self?.handleObserverCallback(
|
|
170
|
-
typeIdentifier: typeIdentifier,
|
|
171
|
-
error: error
|
|
172
|
-
)
|
|
173
|
-
// Must call the completion handler promptly so iOS knows we processed the update.
|
|
174
|
-
completionHandler()
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
healthStore.execute(query)
|
|
178
|
-
|
|
179
|
-
healthStore.enableBackgroundDelivery(for: sampleType, frequency: frequency) { success, error in
|
|
180
|
-
if let error = error {
|
|
181
|
-
print("[react-native-healthkit] BackgroundDeliveryManager: enableBackgroundDelivery failed for \(typeIdentifier): \(error.localizedDescription)")
|
|
182
|
-
} else if !success {
|
|
183
|
-
print("[react-native-healthkit] BackgroundDeliveryManager: enableBackgroundDelivery returned false for \(typeIdentifier)")
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
queue.sync(flags: .barrier) {
|
|
188
|
-
self.observerQueries[typeIdentifier] = query
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
private func handleObserverCallback(typeIdentifier: String, error: Error?) {
|
|
194
|
-
let errorMessage = error?.localizedDescription
|
|
195
|
-
os_log("observer fired: %{public}@", log: bgLog, type: .info, typeIdentifier)
|
|
196
|
-
|
|
197
|
-
// Ask iOS for real execution time before doing anything else, so the
|
|
198
|
-
// process survives long enough for Hermes to boot and the JS callback to
|
|
199
|
-
// run — see the comment at this query's registration above.
|
|
200
|
-
var backgroundTaskId = UIBackgroundTaskIdentifier.invalid
|
|
201
|
-
let endTask: () -> Void = { [weak self] in
|
|
202
|
-
self?.queue.sync(flags: .barrier) {
|
|
203
|
-
guard backgroundTaskId != .invalid else { return }
|
|
204
|
-
UIApplication.shared.endBackgroundTask(backgroundTaskId)
|
|
205
|
-
backgroundTaskId = .invalid
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
backgroundTaskId = UIApplication.shared.beginBackgroundTask(withName: "healthkit-observer-\(typeIdentifier)") {
|
|
209
|
-
os_log("background task expired: %{public}@", log: bgLog, type: .info, typeIdentifier)
|
|
210
|
-
endTask()
|
|
211
|
-
}
|
|
212
|
-
os_log("background task started: %{public}@", log: bgLog, type: .info, typeIdentifier)
|
|
213
|
-
|
|
214
|
-
queue.sync(flags: .barrier) {
|
|
215
|
-
if let callback = self.typeCallbacks[typeIdentifier] {
|
|
216
|
-
DispatchQueue.main.async {
|
|
217
|
-
os_log("dispatching to per-type JS callback: %{public}@", log: bgLog, type: .info, typeIdentifier)
|
|
218
|
-
callback(typeIdentifier, errorMessage)
|
|
219
|
-
}
|
|
220
|
-
} else if let callback = self.jsCallback {
|
|
221
|
-
// JS is connected — dispatch to main thread for JSI safety
|
|
222
|
-
DispatchQueue.main.async {
|
|
223
|
-
os_log("dispatching to global JS callback: %{public}@", log: bgLog, type: .info, typeIdentifier)
|
|
224
|
-
callback(typeIdentifier, errorMessage)
|
|
225
|
-
}
|
|
226
|
-
} else {
|
|
227
|
-
// JS not ready yet — queue the event for later
|
|
228
|
-
os_log("no JS callback yet, queuing: %{public}@", log: bgLog, type: .info, typeIdentifier)
|
|
229
|
-
self.pendingEvents.append((typeIdentifier: typeIdentifier, errorMessage: errorMessage))
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// Hold the task open for a fixed, generous window rather than trying to
|
|
234
|
-
// ack precisely when JS finishes — Hermes boot plus the JS callback's own
|
|
235
|
-
// async work (HealthKit reads + Supabase upsert) is unpredictable, and a
|
|
236
|
-
// completion-ack channel back from JS isn't worth building on the first
|
|
237
|
-
// pass for a personal-use app. First place to revisit if verification
|
|
238
|
-
// shows this window is too tight.
|
|
239
|
-
DispatchQueue.main.asyncAfter(deadline: .now() + 25) {
|
|
240
|
-
os_log("background task window elapsed: %{public}@", log: bgLog, type: .info, typeIdentifier)
|
|
241
|
-
endTask()
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// Local type resolution that doesn't depend on NitroModules (which isn't available at AppDelegate time).
|
|
246
|
-
// Uses the older factory APIs (quantityType(forIdentifier:) etc.) for iOS 13+ compatibility.
|
|
247
|
-
private func sampleTypeFromString(_ identifier: String) -> HKSampleType? {
|
|
248
|
-
if identifier.starts(with: "HKQuantityTypeIdentifier") {
|
|
249
|
-
let typeId = HKQuantityTypeIdentifier(rawValue: identifier)
|
|
250
|
-
return HKSampleType.quantityType(forIdentifier: typeId)
|
|
251
|
-
}
|
|
252
|
-
if identifier.starts(with: "HKCategoryTypeIdentifier") {
|
|
253
|
-
let typeId = HKCategoryTypeIdentifier(rawValue: identifier)
|
|
254
|
-
return HKSampleType.categoryType(forIdentifier: typeId)
|
|
255
|
-
}
|
|
256
|
-
if identifier == "HKWorkoutTypeIdentifier" {
|
|
257
|
-
return HKSampleType.workoutType()
|
|
258
|
-
}
|
|
259
|
-
if identifier.starts(with: "HKCorrelationTypeIdentifier") {
|
|
260
|
-
let typeId = HKCorrelationTypeIdentifier(rawValue: identifier)
|
|
261
|
-
return HKSampleType.correlationType(forIdentifier: typeId)
|
|
262
|
-
}
|
|
263
|
-
if identifier == "HKAudiogramSampleType" {
|
|
264
|
-
return HKObjectType.audiogramSampleType()
|
|
265
|
-
}
|
|
266
|
-
if identifier == "HKDataTypeIdentifierHeartbeatSeries" || identifier == "HKWorkoutRouteTypeIdentifier" {
|
|
267
|
-
return HKObjectType.seriesType(forIdentifier: identifier)
|
|
268
|
-
}
|
|
269
|
-
if identifier == "HKElectrocardiogramType" {
|
|
270
|
-
if #available(iOS 14.0, *) {
|
|
271
|
-
return HKSampleType.electrocardiogramType()
|
|
272
|
-
}
|
|
273
|
-
return nil
|
|
274
|
-
}
|
|
275
|
-
return nil
|
|
276
|
-
}
|
|
277
|
-
}
|
package/ios/Bridge.h
DELETED
package/ios/ExceptionCatcher.h
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
#import <Foundation/Foundation.h>
|
|
2
|
-
#import <HealthKit/HealthKit.h>
|
|
3
|
-
|
|
4
|
-
HKUnit * _Nullable HKUnitFromStringCatchingExceptions(NSString * _Nonnull unitString, NSError * _Nullable * _Nullable outError);
|
|
5
|
-
BOOL RunBlockCatchingObjCExceptions(void (NS_NOESCAPE ^_Nonnull block)(void), NSError * _Nullable * _Nullable outError);
|
package/ios/ExceptionCatcher.mm
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
#import "ExceptionCatcher.h"
|
|
2
|
-
|
|
3
|
-
HKUnit * _Nullable HKUnitFromStringCatchingExceptions(NSString * _Nonnull unitString, NSError * _Nullable * _Nullable outError) {
|
|
4
|
-
if (outError) { *outError = nil; }
|
|
5
|
-
@try {
|
|
6
|
-
HKUnit *unit = [HKUnit unitFromString:unitString];
|
|
7
|
-
return unit;
|
|
8
|
-
}
|
|
9
|
-
@catch (NSException *exception) {
|
|
10
|
-
if (outError) {
|
|
11
|
-
NSDictionary *userInfo = exception.userInfo ?: @{};
|
|
12
|
-
|
|
13
|
-
*outError = [NSError errorWithDomain:exception.name code:0 userInfo:userInfo];
|
|
14
|
-
}
|
|
15
|
-
return nil;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
BOOL RunBlockCatchingObjCExceptions(void (NS_NOESCAPE ^block)(void), NSError * _Nullable * _Nullable outError) {
|
|
20
|
-
if (outError) { *outError = nil; }
|
|
21
|
-
@try {
|
|
22
|
-
block();
|
|
23
|
-
return YES;
|
|
24
|
-
}
|
|
25
|
-
@catch (NSException *exception) {
|
|
26
|
-
if (outError) {
|
|
27
|
-
NSDictionary *userInfo = exception.userInfo ?: @{};
|
|
28
|
-
*outError = [NSError errorWithDomain:exception.name code:0 userInfo:userInfo];
|
|
29
|
-
}
|
|
30
|
-
return NO;
|
|
31
|
-
}
|
|
32
|
-
}
|