diff --git a/.github/workflows/lint_pod.yml b/.github/workflows/lint_pod.yml new file mode 100644 index 0000000..471c5a1 --- /dev/null +++ b/.github/workflows/lint_pod.yml @@ -0,0 +1,24 @@ +name: Lint Pod + +on: + pull_request: + branches: [ master ] + types: [ assigned, opened, synchronize, reopened ] + +jobs: + pod-lint: + name: Lint Pod + runs-on: macos-latest + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Load and Install Bundle Cache + uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.6 + bundler-cache: true + + - name: Lint Pod + run: bundle exec pod lib lint HealthKitReporter.podspec --allow-warnings diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml new file mode 100644 index 0000000..2cc497f --- /dev/null +++ b/.github/workflows/swift.yml @@ -0,0 +1,22 @@ +name: Swift + +on: + pull_request: + branches: [ master ] + types: [ assigned, opened, synchronize, reopened ] + +jobs: + build: + + runs-on: macos-latest + + steps: + - uses: actions/checkout@v3 + - name: Generate project + run: swift package generate-xcodeproj + - name: Build + run: xcodebuild clean build -project "HealthKitReporter.xcodeproj" -scheme "HealthKitReporter-Package" -destination "platform=iOS Simulator,name=iPhone 12 Pro,OS=latest" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO ONLY_ACTIVE_ARCH=NO + - name: Run tests + run: xcodebuild clean test -project "HealthKitReporter.xcodeproj" -scheme "HealthKitReporter-Package" -destination "platform=iOS Simulator,name=iPhone 12 Pro,OS=latest" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO ONLY_ACTIVE_ARCH=NO + + diff --git a/CHANGELOG.md b/CHANGELOG.md index 1414fcf..b0a2340 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,54 @@ +## [3.1.0] - 08.01.2024. + +* Added support for HKClinicalRecord + +## [3.0.0] - 12.03.2023. + +* Check for Health data availability +* CHanged the way of creating HKR instance + +## [2.0.0] - 29.10.2022. + +* Revamp metadata + +## [1.7.0] - 29.10.2022. + +* Add new iOS 16 types (also missing iOS 15 types) + +## [1.6.9] - 27.05.2022. + +* Add copyWith methods to Correlation + +## [1.6.8] - 27.05.2022. + +* Small fix with Correlation save in health repository + +## [1.6.7] - 27.05.2022. + +* Small fix with Correlation copyWith method + +## [1.6.6] - 27.05.2022. + +* Add saving Correlation samples + +## [1.6.5] - 18.04.2022. + +* ECG with Voltage measurements in one query on demand + +## [1.6.4] - 17.04.2022. + +* ECG with Voltage measurements in one query + +## [1.6.3] - 16.04.2022. + +* add from dictionary static factory for WorkoutRoute +* minor fixes in the code + +## [1.6.2] - 23.10.2021. + +* Fix timestamps bug +* add from dictionary static factory for HeartbeatSeries + ## [1.6.1] - 15.10.2021. * return HeartbeatSeries as a collection of samples, each has own collection of measurements diff --git a/Example/HealthKitReporter.xcodeproj/project.pbxproj b/Example/HealthKitReporter.xcodeproj/project.pbxproj index 4941f9d..75d49fd 100644 --- a/Example/HealthKitReporter.xcodeproj/project.pbxproj +++ b/Example/HealthKitReporter.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; }; 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; }; 607FACEC1AFB9204008FA782 /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACEB1AFB9204008FA782 /* Tests.swift */; }; + 783B1F752840FDF100B2B690 /* HealthKitReporterService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 783B1F742840FDF100B2B690 /* HealthKitReporterService.swift */; }; C0343CAAEF443B61427014A1 /* Pods_HealthKitReporter_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9E025C132111D8252E831EEC /* Pods_HealthKitReporter_Example.framework */; }; E98E55B8B5FB6C7A64A3DB25 /* Pods_HealthKitReporter_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15F8173830CFE392F3EA6A3D /* Pods_HealthKitReporter_Tests.framework */; }; /* End PBXBuildFile section */ @@ -54,8 +55,9 @@ 607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 607FACEB1AFB9204008FA782 /* Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = ""; }; 7003F1C7C75718FEDF8637AF /* Pods-HealthKitReporter_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HealthKitReporter_Tests.release.xcconfig"; path = "Target Support Files/Pods-HealthKitReporter_Tests/Pods-HealthKitReporter_Tests.release.xcconfig"; sourceTree = ""; }; + 783B1F742840FDF100B2B690 /* HealthKitReporterService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HealthKitReporterService.swift; sourceTree = ""; }; 784CB4452F8A563A8EC84C82 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; - 8274ECC55EA5E895980E76E1 /* HealthKitReporter.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = HealthKitReporter.podspec; path = ../HealthKitReporter.podspec; sourceTree = ""; }; + 8274ECC55EA5E895980E76E1 /* HealthKitReporter.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = HealthKitReporter.podspec; path = ../HealthKitReporter.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 9E025C132111D8252E831EEC /* Pods_HealthKitReporter_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_HealthKitReporter_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; E99BA72C15D1884C0B1E5444 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; /* End PBXFileReference section */ @@ -86,6 +88,7 @@ children = ( 17FB97D02581399C0092B9E9 /* LocalNotificationManager.swift */, 17FB97D925813A250092B9E9 /* LocalNotification.swift */, + 783B1F742840FDF100B2B690 /* HealthKitReporterService.swift */, ); name = Service; sourceTree = ""; @@ -243,7 +246,7 @@ CreatedOnToolsVersion = 6.3.1; DevelopmentTeam = MAVP5V2N7V; LastSwiftMigration = 1200; - ProvisioningStyle = Manual; + ProvisioningStyle = Automatic; }; 607FACE41AFB9204008FA782 = { CreatedOnToolsVersion = 6.3.1; @@ -382,6 +385,7 @@ 17FB97DA25813A250092B9E9 /* LocalNotification.swift in Sources */, 17FB97D12581399C0092B9E9 /* LocalNotificationManager.swift in Sources */, 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */, + 783B1F752840FDF100B2B690 /* HealthKitReporterService.swift in Sources */, 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -474,7 +478,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 1.6.1; + MARKETING_VERSION = 3.0.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -525,7 +529,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 1.6.1; + MARKETING_VERSION = 3.0.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; @@ -539,15 +543,15 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = HealthKitReporter_Example.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; - DEVELOPMENT_TEAM = MAVP5V2N7V; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = HealthKitReporter/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MODULE_NAME = ExampleApp; PRODUCT_BUNDLE_IDENTIFIER = "com.kvs.demo.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = HealthKitReporter; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 5.0; }; @@ -559,15 +563,15 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = HealthKitReporter_Example.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; - DEVELOPMENT_TEAM = MAVP5V2N7V; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = HealthKitReporter/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MODULE_NAME = ExampleApp; PRODUCT_BUNDLE_IDENTIFIER = "com.kvs.demo.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = HealthKitReporter; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 5.0; }; diff --git a/Example/HealthKitReporter.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Example/HealthKitReporter.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Example/HealthKitReporter.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Example/HealthKitReporter/AppDelegate.swift b/Example/HealthKitReporter/AppDelegate.swift index d5df477..c9b89cb 100644 --- a/Example/HealthKitReporter/AppDelegate.swift +++ b/Example/HealthKitReporter/AppDelegate.swift @@ -21,49 +21,45 @@ class AppDelegate: UIResponder, UIApplicationDelegate { ) -> Bool { let localNotificationManager = LocalNotificationManager() localNotificationManager.requestPermission { (_, _) in } - do { - let reporter = try HealthKitReporter() - let types: [SampleType] = [ - QuantityType.stepCount, - QuantityType.heartRate, - QuantityType.distanceCycling, - CategoryType.sleepAnalysis - ] - reporter.manager.requestAuthorization( - toRead: types, - toWrite: types - ) { (success, error) in - if success && error == nil { - for type in types { - do { - let query = try reporter.observer.observerQuery( - type: type - ) { (_, identifier, _) in - if let identifier = identifier { - let notification = LocalNotification( - title: "Observed", - subtitle: identifier - ) - localNotificationManager.scheduleNotification(notification) - } + let reporter = HealthKitReporter() + let types: [SampleType] = [ + QuantityType.stepCount, + QuantityType.heartRate, + QuantityType.distanceCycling, + CategoryType.sleepAnalysis + ] + reporter.manager.requestAuthorization( + toRead: types, + toWrite: types + ) { (success, error) in + if success && error == nil { + for type in types { + do { + let query = try reporter.observer.observerQuery( + type: type + ) { (_, identifier, _) in + if let identifier = identifier { + let notification = LocalNotification( + title: "Observed", + subtitle: identifier + ) + localNotificationManager.scheduleNotification(notification) } - reporter.observer.enableBackgroundDelivery( - type: type, - frequency: .immediate - ) { (_, error) in - if error == nil { - print("enabled") - } + } + reporter.observer.enableBackgroundDelivery( + type: type, + frequency: .immediate + ) { (_, error) in + if error == nil { + print("enabled") } - reporter.manager.executeQuery(query) - } catch { - print(error) } + reporter.manager.executeQuery(query) + } catch { + print(error) } } } - } catch { - print(error) } return true } diff --git a/Example/HealthKitReporter/Base.lproj/Main.storyboard b/Example/HealthKitReporter/Base.lproj/Main.storyboard index 0fe53cd..6713a1e 100644 --- a/Example/HealthKitReporter/Base.lproj/Main.storyboard +++ b/Example/HealthKitReporter/Base.lproj/Main.storyboard @@ -1,9 +1,9 @@ - + - + @@ -46,9 +46,9 @@ diff --git a/Example/HealthKitReporter/HealthKitReporterService.swift b/Example/HealthKitReporter/HealthKitReporterService.swift new file mode 100644 index 0000000..40a2809 --- /dev/null +++ b/Example/HealthKitReporter/HealthKitReporterService.swift @@ -0,0 +1,358 @@ +// +// HealthKitReporterService.swift +// HealthKitReporter_Example +// +// Created by Victor Kachalov on 27.05.22. +// Copyright © 2022 CocoaPods. All rights reserved. +// + +import HealthKitReporter + +final class HealthKitReporterService { + private var reporter: HealthKitReporter? + + private var typesToRead: [ObjectType] { + var types: [ObjectType] = [ + QuantityType.stepCount, + QuantityType.heartRate, + QuantityType.bloodPressureSystolic, + QuantityType.bloodPressureDiastolic, + CategoryType.sleepAnalysis, + QuantityType.heartRateVariabilitySDNN, + SeriesType.heartbeatSeries, + WorkoutType.workoutType, + SeriesType.workoutRoute, + ] + if #available(iOS 14.0, *) { + types.append(ElectrocardiogramType.electrocardiogramType) + } + return types + } + private let typesToWrite: [QuantityType] = [ + .stepCount, + .bloodPressureSystolic, + .bloodPressureDiastolic, + ] + + private var predicate: NSPredicate { + let now = Date() + return Query.predicateForSamples( + withStart: now.addingTimeInterval(-1 * 3600 * 3600 * 24), + end: now, + options: .strictEndDate + ) + } + + init() { + if HealthKitReporter.isHealthDataAvailable { + reporter = HealthKitReporter() + } else { + print("HealthKitReporter is not available") + } + } + + func requestAuthorization(completion: @escaping StatusCompletionBlock) { + reporter?.manager.requestAuthorization( + toRead: typesToRead, + toWrite: typesToWrite, + completion: completion + ) + } + + func readCategories() { + let manager = reporter?.manager + let reader = reporter?.reader + if let categoryTypes = typesToRead.filter({ $0 is CategoryType}) as? [CategoryType] { + for type in categoryTypes { + do { + if let query = try reader?.categoryQuery( + type: type, + predicate: predicate, + resultsHandler: { results, error in + if error == nil { + for element in results { + do { + print(try element.encoded()) + } catch { + print(error) + } + } + } else { + print(error ?? "error") + } + }) { + manager?.executeQuery(query) + } + } catch { + print(error) + } + } + } + } + + func readElectrocardiogram() { + let manager = reporter?.manager + let reader = reporter?.reader + do { + if #available(iOS 14.0, *) { + if let seriesQuery = try reader?.electrocardiogramQuery( + predicate: predicate, + resultsHandler: { samples, error in + if error == nil { + do { + print("Electrocardiograms:", try samples.encoded()) + } catch { + print(error) + } + } else { + print(error ?? "readElectrocardiogram error") + } + }) { + manager?.executeQuery(seriesQuery) + } + } else { + print("ecg is not available") + } + } catch { + print(error) + } + } + + func readHearbeatSeries() { + let manager = reporter?.manager + let reader = reporter?.reader + do { + if let seriesQuery = try reader?.heartbeatSeriesQuery( + predicate: predicate, + resultsHandler: { samples, error in + if error == nil { + do { + print("HearbeatSeries", try samples.encoded()) + } catch { + print(error) + } + } else { + print(error ?? "readHearbeatSeries error") + } + }) { + manager?.executeQuery(seriesQuery) + } + } catch { + print(error) + } + } + + func readWorkoutRoutes() { + let manager = reporter?.manager + let reader = reporter?.reader + do { + if let seriesQuery = try reader?.workoutRouteQuery( + predicate: predicate, + resultsHandler: { samples, error in + if error == nil { + do { + print("WorkoutRoutes:", try samples.encoded()) + } catch { + print(error) + } + } else { + print(error ?? "readWorkoutRoutes error") + } + }) { + manager?.executeQuery(seriesQuery) + } + } catch { + print(error) + } + } + + func readQuantitiesAndStatistics() { + let manager = reporter?.manager + let reader = reporter?.reader + if let quantityTypes = typesToRead.filter({ $0 is QuantityType}) as? [QuantityType] { + manager?.preferredUnits(for: quantityTypes) { (preferredUnits, error) in + if error == nil { + for preferredUnit in preferredUnits { + do { + if let quantityQuery = try reader?.quantityQuery( + type: try QuantityType.make(from: preferredUnit.identifier), + unit: preferredUnit.unit, + resultsHandler: { (results, error) in + if error == nil { + for element in results { + do { + print("Quantity", try element.encoded()) + } catch { + print(error) + } + } + } else { + print(error ?? "readQuantitiesAndStatistics error") + } + } + ) { + manager?.executeQuery(quantityQuery) + } + if let statisticsQuery = try reader?.statisticsQuery( + type: try QuantityType.make(from: preferredUnit.identifier), + unit: preferredUnit.unit, + completionHandler: { (element, error) in + if error == nil { + do { + print("Statistics", try element.encoded()) + } catch { + print(error) + } + } else { + print(error ?? "readQuantitiesAndStatistics error") + } + } + ) { + manager?.executeQuery(statisticsQuery) + } + } catch { + print(error) + } + } + } else { + print(error ?? "readQuantitiesAndStatistics error") + } + } + } + } + + func writeBloodPressureCorrelation() { + let now = Date() + let minuteAgo = now.addingTimeInterval(-60) + let device = Device( + name: "Guy's iPhone", + manufacturer: "Guy", + model: "6.1.1", + hardwareVersion: "some_0", + firmwareVersion: "some_1", + softwareVersion: "some_2", + localIdentifier: "some_3", + udiDeviceIdentifier: "some_4" + ) + let source = Source( + name: "mySource", + bundleIdentifier: "com.kvs.hkreporter" + ) + let operatingSystem = SourceRevision.OperatingSystem( + majorVersion: 1, + minorVersion: 1, + patchVersion: 1 + ) + let sourceRevision = SourceRevision( + source: source, + version: "1.0.0", + productType: "CocoaPod", + systemVersion: "1.0.0.0", + operatingSystem: operatingSystem + ) + let sys = Quantity( + identifier: QuantityType.bloodPressureSystolic.identifier!, + startTimestamp: minuteAgo.timeIntervalSince1970, + endTimestamp: now.timeIntervalSince1970, + device: device, + sourceRevision: sourceRevision, + harmonized: Quantity.Harmonized( + value: 123.0, + unit: "mmHg", + metadata: ["you": "saved it"] + ) + ) + let dias = Quantity( + identifier: QuantityType.bloodPressureDiastolic.identifier!, + startTimestamp: minuteAgo.timeIntervalSince1970, + endTimestamp: now.timeIntervalSince1970, + device: device, + sourceRevision: sourceRevision, + harmonized: Quantity.Harmonized( + value: 83.0, + unit: "mmHg", + metadata: ["you": "saved it"] + ) + ) + let correlation = Correlation( + identifier: CorrelationType.bloodPressure.identifier!, + startTimestamp: minuteAgo.timeIntervalSince1970, + endTimestamp: now.timeIntervalSince1970, + device: device, sourceRevision: sourceRevision, + harmonized: Correlation.Harmonized( + quantitySamples: [sys, dias], + categorySamples: [], + metadata: ["you": "saved it"] + ) + ) + do { + print("BloodPressureCorrelation:", try correlation.encoded()) + let writer = reporter?.writer + writer?.save(sample: correlation) { success, error in + print("BloodPressureCorrelation saved:", success) + print("BloodPressureCorrelation erorr:", error ?? "no erorr") + } + } catch { + print(error) + } + } + + func writeSteps() { + let manager = reporter?.manager + let writer = reporter?.writer + manager?.preferredUnits(for: typesToWrite) { (preferredUnits, _) in + for preferredUnit in preferredUnits { + let identifier = preferredUnit.identifier + guard + identifier == QuantityType.stepCount.identifier + else { + return + } + let now = Date() + let quantity = Quantity( + identifier: identifier, + startTimestamp: now.addingTimeInterval(-60).timeIntervalSince1970, + endTimestamp: now.timeIntervalSince1970, + device: Device( + name: "Guy's iPhone", + manufacturer: "Guy", + model: "6.1.1", + hardwareVersion: "some_0", + firmwareVersion: "some_1", + softwareVersion: "some_2", + localIdentifier: "some_3", + udiDeviceIdentifier: "some_4" + ), + sourceRevision: SourceRevision( + source: Source( + name: "mySource", + bundleIdentifier: "com.kvs.hkreporter" + ), + version: "1.0.0", + productType: "CocoaPod", + systemVersion: "1.0.0.0", + operatingSystem: SourceRevision.OperatingSystem( + majorVersion: 1, + minorVersion: 1, + patchVersion: 1 + ) + ), + harmonized: Quantity.Harmonized( + value: 123.0, + unit: preferredUnit.unit, + metadata: nil + ) + ) + do { + print("StepsQuantity:", try quantity.encoded()) + writer?.save(sample: quantity) { success, error in + print("StepsQuantity saved:", success) + print("StepsQuantity erorr:", error ?? "error") + } + } catch { + print(error) + } + } + } + } +} diff --git a/Example/HealthKitReporter/LocalNotificationManager.swift b/Example/HealthKitReporter/LocalNotificationManager.swift index 1e13c57..000e083 100644 --- a/Example/HealthKitReporter/LocalNotificationManager.swift +++ b/Example/HealthKitReporter/LocalNotificationManager.swift @@ -6,7 +6,6 @@ // Copyright © 2020 Victor Kachalov. All rights reserved. // -import Foundation import UserNotifications class LocalNotificationManager { diff --git a/Example/HealthKitReporter/ViewController.swift b/Example/HealthKitReporter/ViewController.swift index e0b9479..88d9b24 100644 --- a/Example/HealthKitReporter/ViewController.swift +++ b/Example/HealthKitReporter/ViewController.swift @@ -13,34 +13,16 @@ class ViewController: UIViewController { @IBOutlet weak var readButton: UIButton! @IBOutlet weak var writeButton: UIButton! - private var reporter: HealthKitReporter? - private let typesToRead: [ObjectType] = [ - QuantityType.stepCount, - QuantityType.heartRate, - CategoryType.sleepAnalysis, - QuantityType.heartRateVariabilitySDNN, - SeriesType.heartbeatSeries - ] - private let typesToWrite: [QuantityType] = [ - .stepCount - ] + private let healthKitReporterSerivce = HealthKitReporterService() override func viewDidLoad() { super.viewDidLoad() - do { - reporter = try HealthKitReporter() - } catch { - print(error) - } readButton.isEnabled = false writeButton.isEnabled = false } @IBAction func authorizeButtonTapped(_ sender: UIButton) { - reporter?.manager.requestAuthorization( - toRead: typesToRead, - toWrite: typesToWrite - ) { (success, error) in + healthKitReporterSerivce.requestAuthorization { success, error in if success && error == nil { DispatchQueue.main.async { [unowned self] in let alert = UIAlertController( @@ -65,176 +47,16 @@ class ViewController: UIViewController { } } @IBAction func readButtonTapped(_ sender: UIButton) { - read() + healthKitReporterSerivce.readCategories() + healthKitReporterSerivce.readElectrocardiogram() + healthKitReporterSerivce.readQuantitiesAndStatistics() } @IBAction func writeButtonTapped(_ sender: UIButton) { - write { success, error in - DispatchQueue.main.async { [unowned self] in - let alert = UIAlertController( - title: "HK", - message: "HK writing - \(success). \(error != nil ? String(describing: error) : "No errors")", - preferredStyle: .alert - ) - alert.addAction( - UIAlertAction( - title: "OK", - style: .default - ) - ) - self.present(alert, animated: true) - } - } + healthKitReporterSerivce.writeSteps() + healthKitReporterSerivce.writeBloodPressureCorrelation() } - @IBAction func hrSeriesButtonTapped(_ sender: UIButton) { - readSeries() - } - - private func readSeries() { - let manager = reporter?.manager - let reader = reporter?.reader - do { - if let seriesQuery = try reader?.heartbeatSeriesQuery(resultsHandler: { samples, error in - if error == nil { - do { - print(try samples.encoded()) - } catch { - print(error) - } - } else { - print(error ?? "error") - } - }) { - manager?.executeQuery(seriesQuery) - } - } catch { - print(error) - } - } - - private func write(completionHandler: @escaping (Bool, Error?) -> Void) { - let manager = reporter?.manager - let writer = reporter?.writer - manager?.preferredUnits(for: typesToWrite) { (preferredUnits, _) in - for preferredUnit in preferredUnits { - let identifier = preferredUnit.identifier - guard - identifier == QuantityType.stepCount.identifier - else { - return - } - let now = Date() - let quantity = Quantity( - identifier: identifier, - startTimestamp: now.addingTimeInterval(-60).timeIntervalSince1970, - endTimestamp: now.timeIntervalSince1970, - device: Device( - name: "Guy's iPhone", - manufacturer: "Guy", - model: "6.1.1", - hardwareVersion: "some_0", - firmwareVersion: "some_1", - softwareVersion: "some_2", - localIdentifier: "some_3", - udiDeviceIdentifier: "some_4" - ), - sourceRevision: SourceRevision( - source: Source( - name: "mySource", - bundleIdentifier: "com.kvs.hkreporter" - ), - version: "1.0.0", - productType: "CocoaPod", - systemVersion: "1.0.0.0", - operatingSystem: SourceRevision.OperatingSystem( - majorVersion: 1, - minorVersion: 1, - patchVersion: 1 - ) - ), - harmonized: Quantity.Harmonized( - value: 123.0, - unit: preferredUnit.unit, - metadata: nil - ) - ) - writer?.save(sample: quantity, completion: completionHandler) - } - } - } - - private func read() { - let manager = reporter?.manager - let reader = reporter?.reader - do { - if let query = try reader?.categoryQuery(type: .sleepAnalysis, resultsHandler: { results, error in - if error == nil { - for element in results { - do { - print(try element.encoded()) - } catch { - print(error) - } - } - } else { - print(error ?? "error") - } - }) { - manager?.executeQuery(query) - } - } catch { - print(error) - } - if let quantityTypes = typesToRead.filter({ $0 is QuantityType}) as? [QuantityType] { - manager?.preferredUnits(for: quantityTypes) { [unowned self] (preferredUnits, error) in - if error == nil { - for preferredUnit in preferredUnits { - do { - if let quantityQuery = try reader?.quantityQuery( - type: try QuantityType.make(from: preferredUnit.identifier), - unit: preferredUnit.unit, - resultsHandler: { (results, error) in - if error == nil { - for element in results { - do { - print("QUANTITY") - print(try element.encoded()) - } catch { - print(error) - } - } - } else { - print(error ?? "error") - } - } - ) { - manager?.executeQuery(quantityQuery) - } - if let statisticsQuery = try self.reporter?.reader.statisticsQuery( - type: try QuantityType.make(from: preferredUnit.identifier), - unit: preferredUnit.unit, - completionHandler: { (element, error) in - if error == nil { - do { - print("STATISTICS") - print(try element.encoded()) - } catch { - print(error) - } - } else { - print(error ?? "error") - } - } - ) { - manager?.executeQuery(statisticsQuery) - } - } catch { - print(error) - } - } - } else { - print(error ?? "error") - } - } - } + @IBAction func seriesButtonTapped(_ sender: UIButton) { + healthKitReporterSerivce.readWorkoutRoutes() + healthKitReporterSerivce.readHearbeatSeries() } } diff --git a/Example/Podfile b/Example/Podfile index 1196e00..8f22440 100644 --- a/Example/Podfile +++ b/Example/Podfile @@ -1,11 +1,11 @@ +platform :ios, '9.0' use_frameworks! target 'HealthKitReporter_Example' do - pod 'HealthKitReporter', :path => '../' - - target 'HealthKitReporter_Tests' do - inherit! :search_paths + pod 'HealthKitReporter', :path => '../', :testspecs => ['Tests'] +end - - end +target 'HealthKitReporter_Tests' do + inherit! :search_paths end + diff --git a/Example/Podfile.lock b/Example/Podfile.lock index 2fcad52..1d4d94d 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -1,16 +1,18 @@ PODS: - - HealthKitReporter (0.1.0) + - HealthKitReporter (1.7.0) + - HealthKitReporter/Tests (1.7.0) DEPENDENCIES: - HealthKitReporter (from `../`) + - HealthKitReporter/Tests (from `../`) EXTERNAL SOURCES: HealthKitReporter: :path: "../" SPEC CHECKSUMS: - HealthKitReporter: 101f590db77a0c3153df14478144b85879d6fba8 + HealthKitReporter: c47cb09099b218c2717b8c3b884ee683edf57d95 -PODFILE CHECKSUM: 23abae3089785275304b0626e117fcbe304f3915 +PODFILE CHECKSUM: 42dc208a4788fd9b7d8eebf0c62dd84606fddf4d -COCOAPODS: 1.9.3 +COCOAPODS: 1.11.2 diff --git a/Example/Pods/Local Podspecs/HealthKitReporter.podspec.json b/Example/Pods/Local Podspecs/HealthKitReporter.podspec.json index 8a158a4..426328c 100644 --- a/Example/Pods/Local Podspecs/HealthKitReporter.podspec.json +++ b/Example/Pods/Local Podspecs/HealthKitReporter.podspec.json @@ -1,22 +1,32 @@ { "name": "HealthKitReporter", - "version": "0.1.0", - "summary": "A short description of HealthKitReporter.", - "description": "TODO: Add long description of the pod here.", - "homepage": "https://github.com/Victor Kachalov/HealthKitReporter", + "version": "1.7.0", + "summary": "HealthKitReporter. A wrapper for HealthKit framework.", + "swift_versions": "5.3", + "description": "Helps to write or read data from Apple Health via HealthKit framework.", + "homepage": "https://github.com/VictorKachalov/HealthKitReporter", "license": { "type": "MIT", "file": "LICENSE" }, "authors": { - "Victor Kachalov": "victor.kachalov@thryve.de" + "Victor Kachalov": "victorkachalov@gmail.com" }, "source": { - "git": "https://github.com/Victor Kachalov/HealthKitReporter.git", - "tag": "0.1.0" + "git": "https://github.com/VictorKachalov/HealthKitReporter.git", + "tag": "1.7.0" }, + "social_media_url": "https://www.facebook.com/profile.php?id=1700091944", "platforms": { - "ios": "8.0" + "ios": "9.0" }, - "source_files": "HealthKitReporter/Classes/**/*" + "source_files": "Sources/**/*", + "testspecs": [ + { + "name": "Tests", + "test_type": "unit", + "source_files": "Tests/*.swift" + } + ], + "swift_version": "5.3" } diff --git a/Example/Pods/Manifest.lock b/Example/Pods/Manifest.lock index 2fcad52..1d4d94d 100644 --- a/Example/Pods/Manifest.lock +++ b/Example/Pods/Manifest.lock @@ -1,16 +1,18 @@ PODS: - - HealthKitReporter (0.1.0) + - HealthKitReporter (1.7.0) + - HealthKitReporter/Tests (1.7.0) DEPENDENCIES: - HealthKitReporter (from `../`) + - HealthKitReporter/Tests (from `../`) EXTERNAL SOURCES: HealthKitReporter: :path: "../" SPEC CHECKSUMS: - HealthKitReporter: 101f590db77a0c3153df14478144b85879d6fba8 + HealthKitReporter: c47cb09099b218c2717b8c3b884ee683edf57d95 -PODFILE CHECKSUM: 23abae3089785275304b0626e117fcbe304f3915 +PODFILE CHECKSUM: 42dc208a4788fd9b7d8eebf0c62dd84606fddf4d -COCOAPODS: 1.9.3 +COCOAPODS: 1.11.2 diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index f1511ed..d281d83 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -7,562 +7,673 @@ objects = { /* Begin PBXBuildFile section */ - 040EFF0726E4C86C00D37F04 /* Extensions+HKCategoryValueAudioExposureEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 040EFF0626E4C86C00D37F04 /* Extensions+HKCategoryValueAudioExposureEvent.swift */; }; - 040EFF0926E4C91700D37F04 /* Extensions+HKCategoryValueSleepAnalysis.swift in Sources */ = {isa = PBXBuildFile; fileRef = 040EFF0826E4C91700D37F04 /* Extensions+HKCategoryValueSleepAnalysis.swift */; }; - 040EFF0B26E4C97500D37F04 /* Extensions+HKCategoryValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 040EFF0A26E4C97500D37F04 /* Extensions+HKCategoryValue.swift */; }; - 040EFF0D26E4C9A900D37F04 /* Extensions+HKCategoryValueMenstrualFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 040EFF0C26E4C9A900D37F04 /* Extensions+HKCategoryValueMenstrualFlow.swift */; }; - 040EFF0F26E4C9FB00D37F04 /* Extensions+HKCategoryValueOvulationTestResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 040EFF0E26E4C9FB00D37F04 /* Extensions+HKCategoryValueOvulationTestResult.swift */; }; - 040EFF1126E4CA3600D37F04 /* Extensions+HKCategoryValueCervicalMucusQuality.swift in Sources */ = {isa = PBXBuildFile; fileRef = 040EFF1026E4CA3600D37F04 /* Extensions+HKCategoryValueCervicalMucusQuality.swift */; }; - 040EFF1326E4CA6000D37F04 /* Extensions+HKCategoryValueAppleStandHour.swift in Sources */ = {isa = PBXBuildFile; fileRef = 040EFF1226E4CA6000D37F04 /* Extensions+HKCategoryValueAppleStandHour.swift */; }; - 040EFF1526E4CAE200D37F04 /* Extensions+HKCategoryValueLowCardioFitnessEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 040EFF1426E4CAE200D37F04 /* Extensions+HKCategoryValueLowCardioFitnessEvent.swift */; }; - 040EFF1726E4CB2500D37F04 /* Extensions+HKCategoryValueSeverity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 040EFF1626E4CB2500D37F04 /* Extensions+HKCategoryValueSeverity.swift */; }; - 040EFF1926E4CB8700D37F04 /* Extensions+HKCategoryValuePresence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 040EFF1826E4CB8700D37F04 /* Extensions+HKCategoryValuePresence.swift */; }; - 040EFF1B26E4CBD800D37F04 /* Extensions+HKCategoryValueAppetiteChanges.swift in Sources */ = {isa = PBXBuildFile; fileRef = 040EFF1A26E4CBD800D37F04 /* Extensions+HKCategoryValueAppetiteChanges.swift */; }; - 040EFF1D26E4CC1500D37F04 /* Extensions+HKCategoryValueHeadphoneAudioExposureEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 040EFF1C26E4CC1500D37F04 /* Extensions+HKCategoryValueHeadphoneAudioExposureEvent.swift */; }; - 040EFF1F26E4CCCC00D37F04 /* Extensions+HKCategoryValueEnvironmentalAudioExposureEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 040EFF1E26E4CCCC00D37F04 /* Extensions+HKCategoryValueEnvironmentalAudioExposureEvent.swift */; }; - 040EFF2126E4CD0500D37F04 /* Extensions+HKCategoryValueContraceptive.swift in Sources */ = {isa = PBXBuildFile; fileRef = 040EFF2026E4CD0500D37F04 /* Extensions+HKCategoryValueContraceptive.swift */; }; - 042023DC26178860001C40F7 /* Extensions+HKWorkoutConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0420239126178860001C40F7 /* Extensions+HKWorkoutConfiguration.swift */; }; - 042023DD26178860001C40F7 /* Extensions+HKBloodType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0420239226178860001C40F7 /* Extensions+HKBloodType.swift */; }; - 042023DE26178860001C40F7 /* Extensions+HKStatistics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0420239326178860001C40F7 /* Extensions+HKStatistics.swift */; }; - 042023DF26178860001C40F7 /* Extensions+HKWorkoutActivityType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0420239426178860001C40F7 /* Extensions+HKWorkoutActivityType.swift */; }; - 042023E026178860001C40F7 /* Extensions+String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0420239526178860001C40F7 /* Extensions+String.swift */; }; - 042023E126178860001C40F7 /* Extensions+HKCategoryType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0420239626178860001C40F7 /* Extensions+HKCategoryType.swift */; }; - 042023E226178860001C40F7 /* Extensions+HKCorrelation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0420239726178860001C40F7 /* Extensions+HKCorrelation.swift */; }; - 042023E326178860001C40F7 /* Extensions+Double.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0420239826178860001C40F7 /* Extensions+Double.swift */; }; - 042023E426178860001C40F7 /* Extensions+HKFitzpatrickSkinType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0420239926178860001C40F7 /* Extensions+HKFitzpatrickSkinType.swift */; }; - 042023E526178860001C40F7 /* Extensions+HKCategorySample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0420239A26178860001C40F7 /* Extensions+HKCategorySample.swift */; }; - 042023E626178860001C40F7 /* Extensions+HKActivitySummary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0420239B26178860001C40F7 /* Extensions+HKActivitySummary.swift */; }; - 042023E726178860001C40F7 /* Extensions+HKElectrocardiogram.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0420239C26178860001C40F7 /* Extensions+HKElectrocardiogram.swift */; }; - 042023E826178860001C40F7 /* Extensions+HKQuantityType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0420239D26178860001C40F7 /* Extensions+HKQuantityType.swift */; }; - 042023E926178860001C40F7 /* Extensions+HKSample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0420239E26178860001C40F7 /* Extensions+HKSample.swift */; }; - 042023EA26178860001C40F7 /* Extensions+NSPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0420239F26178860001C40F7 /* Extensions+NSPredicate.swift */; }; - 042023EB26178860001C40F7 /* Extensions+Encodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023A026178860001C40F7 /* Extensions+Encodable.swift */; }; - 042023EC26178860001C40F7 /* Extensions+HKWheelchairUse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023A126178860001C40F7 /* Extensions+HKWheelchairUse.swift */; }; - 042023ED26178860001C40F7 /* Extensions+HKSourceRevision.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023A226178860001C40F7 /* Extensions+HKSourceRevision.swift */; }; - 042023EE26178860001C40F7 /* Extensions+HKQuantitiySample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023A326178860001C40F7 /* Extensions+HKQuantitiySample.swift */; }; - 042023EF26178860001C40F7 /* Extensions+DateComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023A426178860001C40F7 /* Extensions+DateComponents.swift */; }; - 042023F026178860001C40F7 /* Extensions+Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023A526178860001C40F7 /* Extensions+Date.swift */; }; - 042023F126178860001C40F7 /* Extensions+HKWorkout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023A626178860001C40F7 /* Extensions+HKWorkout.swift */; }; - 042023F226178860001C40F7 /* Extensions+HKBiologicalSex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023A726178860001C40F7 /* Extensions+HKBiologicalSex.swift */; }; - 042023F326178860001C40F7 /* Extensions+Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023A826178860001C40F7 /* Extensions+Dictionary.swift */; }; - 042023F426178860001C40F7 /* Extensions+HKWorkoutEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023A926178860001C40F7 /* Extensions+HKWorkoutEvent.swift */; }; - 042023F526178860001C40F7 /* Extensions+HKActivityMoveMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023AA26178860001C40F7 /* Extensions+HKActivityMoveMode.swift */; }; - 042023F626178860001C40F7 /* HealthKitObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023AC26178860001C40F7 /* HealthKitObserver.swift */; }; - 042023F726178860001C40F7 /* HealthKitWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023AD26178860001C40F7 /* HealthKitWriter.swift */; }; - 042023F826178860001C40F7 /* SeriesSampleRetriever.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023AF26178860001C40F7 /* SeriesSampleRetriever.swift */; }; - 042023F926178860001C40F7 /* ElectrocardiogramRetriever.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023B026178860001C40F7 /* ElectrocardiogramRetriever.swift */; }; - 042023FA26178860001C40F7 /* HealthKitReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023B126178860001C40F7 /* HealthKitReader.swift */; }; - 042023FB26178860001C40F7 /* HealthKitManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023B226178860001C40F7 /* HealthKitManager.swift */; }; - 042023FD26178860001C40F7 /* Source.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023B626178860001C40F7 /* Source.swift */; }; - 042023FE26178860001C40F7 /* Statistics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023B726178860001C40F7 /* Statistics.swift */; }; - 042023FF26178860001C40F7 /* Workout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023B826178860001C40F7 /* Workout.swift */; }; - 0420240026178860001C40F7 /* Correlation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023B926178860001C40F7 /* Correlation.swift */; }; - 0420240126178860001C40F7 /* Sample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023BA26178860001C40F7 /* Sample.swift */; }; - 0420240226178860001C40F7 /* Quantity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023BB26178860001C40F7 /* Quantity.swift */; }; - 0420240326178860001C40F7 /* WorkoutRoute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023BC26178860001C40F7 /* WorkoutRoute.swift */; }; - 0420240426178860001C40F7 /* DeletedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023BD26178860001C40F7 /* DeletedObject.swift */; }; - 0420240526178860001C40F7 /* Electrocardiogram.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023BE26178860001C40F7 /* Electrocardiogram.swift */; }; - 0420240626178860001C40F7 /* WorkoutEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023BF26178860001C40F7 /* WorkoutEvent.swift */; }; - 0420240726178860001C40F7 /* ActivitySummary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023C026178860001C40F7 /* ActivitySummary.swift */; }; - 0420240826178860001C40F7 /* Category.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023C126178860001C40F7 /* Category.swift */; }; - 0420240926178860001C40F7 /* Identifiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023C226178860001C40F7 /* Identifiable.swift */; }; - 0420240A26178860001C40F7 /* Device.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023C326178860001C40F7 /* Device.swift */; }; - 0420240B26178860001C40F7 /* WorkoutConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023C426178860001C40F7 /* WorkoutConfiguration.swift */; }; - 0420240C26178860001C40F7 /* Characteristic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023C526178860001C40F7 /* Characteristic.swift */; }; - 0420240D26178860001C40F7 /* SourceRevision.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023C626178860001C40F7 /* SourceRevision.swift */; }; - 0420240E26178860001C40F7 /* Original.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023C726178860001C40F7 /* Original.swift */; }; - 0420240F26178860001C40F7 /* UnitConvertable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023C826178860001C40F7 /* UnitConvertable.swift */; }; - 0420241026178860001C40F7 /* CharacteristicType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023CA26178860001C40F7 /* CharacteristicType.swift */; }; - 0420241126178860001C40F7 /* ActivitySummaryType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023CB26178860001C40F7 /* ActivitySummaryType.swift */; }; - 0420241226178860001C40F7 /* QuantityType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023CD26178860001C40F7 /* QuantityType.swift */; }; - 0420241326178860001C40F7 /* CategoryType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023CE26178860001C40F7 /* CategoryType.swift */; }; - 0420241426178860001C40F7 /* SeriesType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023CF26178860001C40F7 /* SeriesType.swift */; }; - 0420241526178860001C40F7 /* ElectrocardiogramType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023D026178860001C40F7 /* ElectrocardiogramType.swift */; }; - 0420241626178860001C40F7 /* SampleType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023D126178860001C40F7 /* SampleType.swift */; }; - 0420241726178860001C40F7 /* DocumentType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023D226178860001C40F7 /* DocumentType.swift */; }; - 0420241826178860001C40F7 /* WorkoutType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023D326178860001C40F7 /* WorkoutType.swift */; }; - 0420241926178860001C40F7 /* CorrelationType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023D426178860001C40F7 /* CorrelationType.swift */; }; - 0420241A26178860001C40F7 /* ObjectType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023D526178860001C40F7 /* ObjectType.swift */; }; - 0420241B26178860001C40F7 /* Payload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023D626178860001C40F7 /* Payload.swift */; }; - 0420241C26178860001C40F7 /* UpdateFrequency.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023D726178860001C40F7 /* UpdateFrequency.swift */; }; - 0420241D26178860001C40F7 /* Harmonizable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023D826178860001C40F7 /* Harmonizable.swift */; }; - 0420241E26178860001C40F7 /* PreferredUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023D926178860001C40F7 /* PreferredUnit.swift */; }; - 0420241F26178860001C40F7 /* HealthKitError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023DA26178860001C40F7 /* HealthKitError.swift */; }; - 0420242026178860001C40F7 /* HealthKitReporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042023DB26178860001C40F7 /* HealthKitReporter.swift */; }; - 04CC38E426E37F970067ABFD /* Extensions+HKWorkoutEventType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04CC38E326E37F970067ABFD /* Extensions+HKWorkoutEventType.swift */; }; - 04F6E1762715D6B800A63807 /* HeartbeatSeries.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04F6E1752715D6B800A63807 /* HeartbeatSeries.swift */; }; - 04F6E1782715DADC00A63807 /* Extensions+HKHeartbeatSeriesSample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04F6E1772715DADC00A63807 /* Extensions+HKHeartbeatSeriesSample.swift */; }; - 1050D86C275F823332DB71B3081511F3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3212113385A8FBBDB272BD23C409FF61 /* Foundation.framework */; }; - 1716C45525278E190037EA4E /* CHANGELOG.md in Resources */ = {isa = PBXBuildFile; fileRef = 1716C45425278E190037EA4E /* CHANGELOG.md */; }; - 1BB37D34E5F48888A5C051AD9AE21C9D /* Pods-HealthKitReporter_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 54E896CEBBB0F7AB51775AD8DB2A3240 /* Pods-HealthKitReporter_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4A2928A4F62607E28C214719CE56A176 /* Pods-HealthKitReporter_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2810499E4BCD5F7A87DDBD10D478C248 /* Pods-HealthKitReporter_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 6D095DA112AF90AB75DFD4484A214215 /* Pods-HealthKitReporter_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = DBB4C8B104BDB5BB5ABE67400176B082 /* Pods-HealthKitReporter_Example-dummy.m */; }; - 6F28EC06A500C967543B8E86760AE5E9 /* Pods-HealthKitReporter_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 775C0010DC236F50A09CDEE5E5B878F4 /* Pods-HealthKitReporter_Tests-dummy.m */; }; - 7351128AFE6D2C348D5CC138E73673A2 /* HealthKitReporter-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 4F7AB517F06E1D1713499728AC55C83C /* HealthKitReporter-dummy.m */; }; - 9EF9A02EEE3BA943B259F5CE9469FEF2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3212113385A8FBBDB272BD23C409FF61 /* Foundation.framework */; }; - B102DF75C35963420AB33D8269899D81 /* HealthKitReporter-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 1418EAB84877F65C010D2DD616A65D44 /* HealthKitReporter-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D679FAEC8D57E3786E2520FA2A1B9307 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3212113385A8FBBDB272BD23C409FF61 /* Foundation.framework */; }; + 019CD4D6FD914C9DB5CC4890D4A82F36 /* Pods-HealthKitReporter_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 775C0010DC236F50A09CDEE5E5B878F4 /* Pods-HealthKitReporter_Tests-dummy.m */; }; + 029D4E0D6599E806E448BEE08DE1F403 /* Extensions+HKVisionPrescriptionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C35147CFB0794752DC14C3CAC878E0F /* Extensions+HKVisionPrescriptionType.swift */; }; + 079AFADF352E0985438CC498831B9544 /* Workout.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC2D54E14A48876FEF4AB7FC0D65A027 /* Workout.swift */; }; + 085C4A223BCECF792391B96C5D0A2B36 /* Extensions+HKBiologicalSex.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0C5308EDBE4A3479D38CB48FCA95B94 /* Extensions+HKBiologicalSex.swift */; }; + 0A73D80BDF12B704A492BCDC31B6DCE9 /* ActivitySummaryType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44545002736B1F05EECB221CEBFAE961 /* ActivitySummaryType.swift */; }; + 0C9C586C9E9F144B0B17E4C6C226703A /* Extensions+HKCategoryValueAppleWalkingSteadinessEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 779D0EE7F0734A26C238E0380C189EC2 /* Extensions+HKCategoryValueAppleWalkingSteadinessEvent.swift */; }; + 0E46AC8F19F9BB4BBC265A7226DB3B55 /* Extensions+HKCategoryValueProgesteroneTestResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FCDDDC9653ECC45320F6CFA3DAF8A4A /* Extensions+HKCategoryValueProgesteroneTestResult.swift */; }; + 140AA65C0D16953B85C007B0D4CCF425 /* Extensions+HKCategoryValueAppleStandHour.swift in Sources */ = {isa = PBXBuildFile; fileRef = B00A32093EC52BD97BC9CD2DE792DBD4 /* Extensions+HKCategoryValueAppleStandHour.swift */; }; + 147CDFDAB74067118EACE3D27B3ABFB4 /* Category.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04FBB513B464D9F96552E98FAE1343BF /* Category.swift */; }; + 15632A43212028B6971FEEF3F4F60EAB /* Quantity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F465225C97C1D55104FE46F280F9740 /* Quantity.swift */; }; + 16F0B23245CA12323EABAA69C2974442 /* HealthKitObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF9C8313AFF8190CEDAE726029E26604 /* HealthKitObserver.swift */; }; + 194DCD765C577F4E4B0F785E3794B782 /* SeriesType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B39A807B10BADAA7683C62A54AE2F1DF /* SeriesType.swift */; }; + 1C5DBEBBC2505BEF589A15C25B28CC17 /* HealthKitError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60CF485456A867C21161376D061AA225 /* HealthKitError.swift */; }; + 200F17D0556D0C72A0A94242E1A07846 /* Correlation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DA4445FA0413B69A507EE04B90E310E /* Correlation.swift */; }; + 20AF3499ADBCC7E9DF3741473AA025B1 /* Extensions+HKFitzpatrickSkinType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 285279B6B26D290EA701D3EC4966C088 /* Extensions+HKFitzpatrickSkinType.swift */; }; + 2157ACD70581E329A9B409B82ABF00EE /* HealthKitReporter-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 921DD3F31C4FBB5AE97A65943317407E /* HealthKitReporter-dummy.m */; }; + 2AA34BF15C2F9E49811A034CD7C86F54 /* ObjectType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BD29D23F901C237B31A5D692F9D9713 /* ObjectType.swift */; }; + 2E4E9C39BC2318A88A21075F3ABE1C59 /* Extensions+HKCategoryValueAppetiteChanges.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8155DF4384A333207865B8FB24B9D8AA /* Extensions+HKCategoryValueAppetiteChanges.swift */; }; + 2E85B9A398B2D95224290927BADC59E8 /* CategoryType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D95556BAE1B44A602CBAA93EDD3BB464 /* CategoryType.swift */; }; + 34B24C3BBF39229859235BB61B180F66 /* Extensions+HKActivityMoveMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48F38C03BC9C922F42622F968658E132 /* Extensions+HKActivityMoveMode.swift */; }; + 355B81ED05D9A2E1226E02948D9CEE65 /* Pods-HealthKitReporter_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 54E896CEBBB0F7AB51775AD8DB2A3240 /* Pods-HealthKitReporter_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3910D69C192F2559F8374D3574ABCF30 /* Extensions+HKCategoryValueLowCardioFitnessEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 850D6A69E2DC43940596668A9534251E /* Extensions+HKCategoryValueLowCardioFitnessEvent.swift */; }; + 3B069AEBF4625FADFA37445B90216EB4 /* Extensions+Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = C36CEC51B9FF98870F6847C451B710FA /* Extensions+Dictionary.swift */; }; + 3B8B32DDDBA4B54B80A4F19CE772D9EF /* Extensions+HKVisionPrescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = EED4C86C81FD5948A1AD11F9C4446C54 /* Extensions+HKVisionPrescription.swift */; }; + 3E6795A277D1ACDDBFC26912FC3950EE /* ActivitySummaryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E295CBB228A75CA020C76C2067BF4C7 /* ActivitySummaryTests.swift */; }; + 40B4F5AA8240A68BEA9CB07284D179B9 /* QuantityType.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6CCC81EA5C6B1365AA83E14BA201559 /* QuantityType.swift */; }; + 4167C4372313D714316FAF687151846C /* PreferredUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B508D98C4C56C97BDB8D0D1BB46E38F /* PreferredUnit.swift */; }; + 426068AD7D31C9A261291B9054F05069 /* Extensions+HKCategoryValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B8A9E7706067AF7560F39C291BEE3AC /* Extensions+HKCategoryValue.swift */; }; + 435C48B0BABA6E0D626BDFF35197E09F /* Extensions+Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = 725EEB8C2CE54A8A15BDD5F3DB916AB3 /* Extensions+Date.swift */; }; + 45029B327ABC591B82420F5B5ACA1546 /* Extensions+HKSourceRevision.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBC7718A4D411B5E691FCAAE7FD47FEF /* Extensions+HKSourceRevision.swift */; }; + 46A4D70A3EF5E6455C6447E5C66293C1 /* Sample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FFDBE6EB771F9C6CA4167E336AF7A87 /* Sample.swift */; }; + 47B04648FE7574C61BDE353E4A0FBEE3 /* Extensions+HKCategoryValueEnvironmentalAudioExposureEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 106F1D0F830265A82D691E1B3C0C316C /* Extensions+HKCategoryValueEnvironmentalAudioExposureEvent.swift */; }; + 551021AFC56F20ACE3F9B75BF91D178A /* ActivitySummary.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAF5FC29558E97773504BFB7A6E3F0B7 /* ActivitySummary.swift */; }; + 5848D7EE868C3B1FCD2CCFE5358BF672 /* Extensions+HKWorkoutConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1F2F3C0D5878CC84A0A2608512482CB /* Extensions+HKWorkoutConfiguration.swift */; }; + 586F99E0C15F52DFC70987226CBCF468 /* Extensions+HKWorkout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C160DDC8F72F8216539DE0DC7E0C1A6 /* Extensions+HKWorkout.swift */; }; + 58DFA3501CE62007A9EA1ECF206E78E2 /* Extensions+HKQuantitiySample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67E73DDC6B7FB70C6BC6A76DD7AD0C93 /* Extensions+HKQuantitiySample.swift */; }; + 5EA48A6869F09486249508AE2AF8448C /* Extensions+Encodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA110780BB027D6B81BD60D0C560AFFA /* Extensions+Encodable.swift */; }; + 5F3B7021E8BB5A6E798FF957004973F5 /* WorkoutConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F24DB46EFB8B2ADE86C9B96CA26545B5 /* WorkoutConfigurationTests.swift */; }; + 5FA118CFDE8A47F3FB23AD777CF90EF6 /* Extensions+String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AEA8093D9225C79AA3F1A0C3DB4AC54 /* Extensions+String.swift */; }; + 631A8CE1D955DF01FBDA22E262D43F08 /* Extensions+HKHeartbeatSeriesSample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82063CBFA5BA4A9FFAD96EC80564B6EF /* Extensions+HKHeartbeatSeriesSample.swift */; }; + 643CB7077DEEFC95C368A001BFF018CC /* WorkoutConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DA80F32525A8BDE69FA77E6CB72B5BE /* WorkoutConfiguration.swift */; }; + 659F9E39C928EEB8A3977418B5A7B593 /* Extensions+HKCategoryValueMenstrualFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F8156E71A7309B2C760AEE3BCB535F4 /* Extensions+HKCategoryValueMenstrualFlow.swift */; }; + 69AC1E9AD1B251C9334137C6A7A7EA50 /* Extensions+DateComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F2596E09A7D67E6EDBD73E42B8FFCA /* Extensions+DateComponents.swift */; }; + 6C4AB9516500B814B5CF21FBF2C602F1 /* SourceRevisionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B983E73004D5D8DDF1A18C149EA2EED5 /* SourceRevisionTests.swift */; }; + 6C771B0934C9169274D7DC1BEE06D6DD /* Extensions+HKCategoryValueAudioExposureEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7A8940EF42B5DB48394C8EEC564DDD2 /* Extensions+HKCategoryValueAudioExposureEvent.swift */; }; + 6CEFD04B650EB3390000DF40063C18C2 /* SampleType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7114076D9A9EBCD319323158DACCB3B /* SampleType.swift */; }; + 6F9BC1C06ED9A7B5662C0AE96147598E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */; }; + 70ED962EB2E153C9FF71449F183EB92C /* Extensions+HKCategoryValueHeadphoneAudioExposureEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2F7E69DFF38A7DCAD305271E21E7B66 /* Extensions+HKCategoryValueHeadphoneAudioExposureEvent.swift */; }; + 72E09764C778579D86111A27DC1C24B3 /* Device.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D69270819100EAB8BDBF1A42474EDED /* Device.swift */; }; + 73548876675C72560DA62B3A054517EE /* Extensions+HKCategoryValueOvulationTestResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACD4232F0A2B118D033985000AD5D0CB /* Extensions+HKCategoryValueOvulationTestResult.swift */; }; + 7354B0B72C6293B4005297E1 /* ClinicalType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7354B0B62C6293B4005297E1 /* ClinicalType.swift */; }; + 7354B0BA2C629433005297E1 /* Extensions+HKClinicalRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7354B0B82C629433005297E1 /* Extensions+HKClinicalRecord.swift */; }; + 7354B0BD2C62945F005297E1 /* ClinicalRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7354B0BC2C62945F005297E1 /* ClinicalRecord.swift */; }; + 7777396AD7F76C1FFA915EDB8D68FDD7 /* Extensions+HKCategoryValueCervicalMucusQuality.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA77ED0476C73CBFC08F47BF12D6D1E9 /* Extensions+HKCategoryValueCervicalMucusQuality.swift */; }; + 7835AED4290DA39000D9CB35 /* Metadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7835AED3290DA39000D9CB35 /* Metadata.swift */; }; + 79023528495E32B002B9378AF8B238C4 /* CorrelationType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D17B2FDE0B6D0320BE2EB63FF8E7C28C /* CorrelationType.swift */; }; + 79534F864D7D0B2D2C1B99B849FF1B6F /* Extensions+Double.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88988A956142E177BE9C9C195EE79691 /* Extensions+Double.swift */; }; + 7CB2390575AE1EC43C925441DAD19CC0 /* Extensions+HKWorkoutEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2977D7A51AC617CDFE96F27412486B8D /* Extensions+HKWorkoutEvent.swift */; }; + 80927CB9E7B68F1848A6CB18316621B6 /* Extensions+HKSample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AB9C2D8B500080A5420C0810894C5E4 /* Extensions+HKSample.swift */; }; + 85C1539D37A1A4DC1455AD6D0F673392 /* Extensions+HKCategoryValueSeverity.swift in Sources */ = {isa = PBXBuildFile; fileRef = EECFB79FD2730DB471F3DB655747E03B /* Extensions+HKCategoryValueSeverity.swift */; }; + 88CB596B65F716E000A9F6EC19080786 /* Extensions+HKWorkoutRoute.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD811C573A49E507F0A87C150AE3AF32 /* Extensions+HKWorkoutRoute.swift */; }; + 8A89D3FA0C3C9932CA9E03FB654AEA8E /* ElectrocardiogramRetriever.swift in Sources */ = {isa = PBXBuildFile; fileRef = B90113B9E28C8E17E86F0B0F1FBF6898 /* ElectrocardiogramRetriever.swift */; }; + 8DFF2F882B6C1B982535857DFDF3AA57 /* DeviceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F9C1D2DC980211C3F4641DE18E0D0F7 /* DeviceTests.swift */; }; + 8F66F2270182E25A44CFA3466CF4738E /* Extensions+HKCategoryValuePresence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CA4849040BD152BBA56AB34E8712EDB /* Extensions+HKCategoryValuePresence.swift */; }; + 9043883185F24CCAF73B1DFADE74B2BC /* Original.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65F22F9819EE157ADFD08520D456C6A4 /* Original.swift */; }; + 915883B325960F95B820446F38D722F1 /* Identifiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14EAB9F96C66944F221F1658FD262635 /* Identifiable.swift */; }; + 9201CAC9BD32E93586C424EDE967F6A0 /* WorkoutTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8BFD5719C667AF1C203A2A09A771312 /* WorkoutTests.swift */; }; + 920D2C33BD40F2FD60637DB22FC1D9E3 /* CharacteristicType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87DB34BFBC9BF8162EBD02D5C6D298C3 /* CharacteristicType.swift */; }; + 9372FFED87F4BCFC2F558F84E6BCFC06 /* Extensions+NSPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AA24F0D87CCAC22B1512D722F8B81C1 /* Extensions+NSPredicate.swift */; }; + 982BD189F9D48B4F1C84726AF8B523EE /* UpdateFrequency.swift in Sources */ = {isa = PBXBuildFile; fileRef = 908029735F55FEA9CACDB0D1A7D54496 /* UpdateFrequency.swift */; }; + 9844D3E4EDD2E806F0916B04CC5086A4 /* DocumentType.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAAC829BB74B370CC624B2BF0FB92560 /* DocumentType.swift */; }; + A4DA272CF9C16C647EE397E650C8965E /* Payload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DEFD53A33731860ACED9D7FDC45A703 /* Payload.swift */; }; + A6113A07AD3E2D34E5E1AE7043980190 /* Extensions+HKQuantityType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D97E81B98A909D030B0362B21F0DD50 /* Extensions+HKQuantityType.swift */; }; + A7B932E5511DCCF597CDF9EA44742AF2 /* Source.swift in Sources */ = {isa = PBXBuildFile; fileRef = 355655E0A1867FAA9D1FAFD4FABB7F4C /* Source.swift */; }; + AB612C2E12FCAAA03993F152F19D2E89 /* CorrelationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C51C0F692BD912CE07C795C872381A68 /* CorrelationTests.swift */; }; + AC99DC4CD498172DCA0F1101F9CB1AD6 /* CategoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23E54060150E4FF1128E7B1BE26ED26 /* CategoryTests.swift */; }; + B066548AEB09F12F3B9C90D2EC881DF7 /* QuantityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1B657204828C2E3722C952AD326C255 /* QuantityTests.swift */; }; + B2E7ACF4D53BF3810256B44734A833C0 /* Extensions+HKCategoryValuePregnancyTestResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E4CB548A95CBF4A96C788AF488B22EA /* Extensions+HKCategoryValuePregnancyTestResult.swift */; }; + B9107578033FD63377AE5FE34612C96C /* Characteristic.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7389FA911D6AAD9522A038D7CAA3770 /* Characteristic.swift */; }; + B97B3E2DC4719994E52D45BDE54F2B36 /* Extensions+HKWorkoutEventType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD8270979E130D9007CC7FFA74E2407 /* Extensions+HKWorkoutEventType.swift */; }; + C0F1A63843EE02234A1A9B1227D0E13D /* HealthKitReporter-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B080F197C40B7ACE4394268D1CDBC6A /* HealthKitReporter-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C1BFD24F9EC16C7FEDB673AB4630A860 /* WorkoutEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = F84D25CD6B9F6BE671048EA498BCD092 /* WorkoutEvent.swift */; }; + C23D7A7BF7D6947B2450C5E6B31C435C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */; }; + C3F370BD24A59AC1833D0ABF52E319FB /* SourceRevision.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98AF73ECB6BABADE8B248920630A75CF /* SourceRevision.swift */; }; + C5CB95D0A0CB1FDE0F28DD6BB711F789 /* HealthKitWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 843D457EC25CABF71EBFA5B80912C088 /* HealthKitWriter.swift */; }; + C671DDF5C71D89FDAECB2196032DC757 /* HeartbeatSeriesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCD513890913592D2CC8AEAA4A52A42D /* HeartbeatSeriesTests.swift */; }; + C96C836B7EDD50A806864069882D7FE7 /* Extensions+HKElectrocardiogram.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DF381181DC7BCFFB41F309825BF2D06 /* Extensions+HKElectrocardiogram.swift */; }; + C9941F0ABF71109D11C4BC874F1CDC0D /* Pods-HealthKitReporter_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = DBB4C8B104BDB5BB5ABE67400176B082 /* Pods-HealthKitReporter_Example-dummy.m */; }; + CA87DE6BAC9353325E52B827A518DD51 /* SourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBD3A4D4F856461FEDF0C9BD870F1D0 /* SourceTests.swift */; }; + CAB57E3D3059CB3AF0C1B7392F1FBD54 /* Electrocardiogram.swift in Sources */ = {isa = PBXBuildFile; fileRef = 021777A613B44D20DDCE3CA6CFED76E4 /* Electrocardiogram.swift */; }; + CB6D1D26CE4CF803639A44758E483AC5 /* Extensions+HKCorrelation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 884CF18D0A5BA4159D6BD793F9F1BC6F /* Extensions+HKCorrelation.swift */; }; + CDBB74195DF3FADDA35B0AD1AD36A282 /* StatisticsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7614D1074DB0BD9144DC75E02B319E09 /* StatisticsTests.swift */; }; + CEEB5EDA0C1FDDA54FD5DC4DFCA9102E /* Extensions+HKWheelchairUse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 822BE42AD8A5F44EFA02C8B679535B70 /* Extensions+HKWheelchairUse.swift */; }; + D0C064564F2D8F4B765CF2261D0E9C7F /* Extensions+HKWorkoutActivityType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C024B54024A1874B482C78F65CC70A /* Extensions+HKWorkoutActivityType.swift */; }; + D42731D55DA0938AAE7AD1201ED4A891 /* Extensions+HKStatistics.swift in Sources */ = {isa = PBXBuildFile; fileRef = A393395C8707BD18CA7E2D5CF3FE4822 /* Extensions+HKStatistics.swift */; }; + D42E72FF3A0C160E1064077C62E7975D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */; }; + D4A68B708717C9CA8010AC7EF5F7E358 /* ElectrocardiogramTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA30DC80B6382A498E796CBFBC0355E5 /* ElectrocardiogramTests.swift */; }; + D4AE1A99C05B6C20139AA1F1F2C5E318 /* HealthKitReporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F203E555184E35EAAD3AD87D89D271B /* HealthKitReporter.swift */; }; + D6635A98D8EDE329E6F3E52F6617BA47 /* SeriesSampleRetriever.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C1816183E171B9EB7ACB57947D6715 /* SeriesSampleRetriever.swift */; }; + D7EAD3F389E691377CD303810BAEFFF3 /* WorkoutRoute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E1E2342E262E1503D3E8EA5D9144B70 /* WorkoutRoute.swift */; }; + D97F6240A09B04FC3B26FCD8E636B7B8 /* HeartbeatSeries.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49E4CCB9A739C5D6C44E6FDE3CBA336A /* HeartbeatSeries.swift */; }; + DA80BDB1E10491AB598D57077ADDA392 /* Extensions+HKCategorySample.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5D11E89F4AA8A564655156AD5D4F8F2 /* Extensions+HKCategorySample.swift */; }; + DD357B36A9B8D96E8DA7136FEC225D37 /* Harmonizable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DAC7CB4A7DBBBA1D3242C5A8790A749 /* Harmonizable.swift */; }; + E05ED46D0B9E502A8509548863F37426 /* Extensions+HKCategoryValueSleepAnalysis.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F13D5F3D30DFF2CB1E1967820E6546A /* Extensions+HKCategoryValueSleepAnalysis.swift */; }; + E859234CF9FACD084BBE36CB32BDC498 /* ElectrocardiogramType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67FC5BA46B00F310A4C8F9DA5DA7B9E8 /* ElectrocardiogramType.swift */; }; + E86D00B074C381527053C300F8793A7A /* Extensions+HKCategoryValueContraceptive.swift in Sources */ = {isa = PBXBuildFile; fileRef = E126ADB64FCC998644BE8A1F2EA58259 /* Extensions+HKCategoryValueContraceptive.swift */; }; + E9A782EE213CC4A9485DF504563E1047 /* VisionPrescriptionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2DCB207B3C0C062B28F5EE3DBFB4B7B /* VisionPrescriptionType.swift */; }; + E9C407EDAF4A8F76F1639238845151B0 /* Extensions+HKCategoryType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D09718B54ED3E490683579AA4C5D5F9 /* Extensions+HKCategoryType.swift */; }; + EA8B3BD7588E42A2DA08A40CC514BDCC /* CharacteristicTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 198D71D3AF21150E7A31E171D9847E1E /* CharacteristicTests.swift */; }; + EAF3612C219AE905B0F96C538C9E1BD1 /* WorkoutType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96183C6EFBB56F5D2AE474F39E897793 /* WorkoutType.swift */; }; + EC10C7A265255331473CED36F50D3AC3 /* Extensions+HKBloodType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3102A396ED211624C89742DC1A2DB605 /* Extensions+HKBloodType.swift */; }; + EC8FBD3CC6A6C33B3B2593EDFE12C37D /* WorkoutRouteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E32F57F22FDB65E7823F8D10B88C959A /* WorkoutRouteTests.swift */; }; + ECB5C12623BFF04405379E36BC404A08 /* VisionPrescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8671054852BAA6C7E7CC6C86B5002C7F /* VisionPrescription.swift */; }; + EE58B4676A7806C9913ABABCC0D4350F /* DeletedObjectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 101CB243B88135DF695DCD79346E7AEF /* DeletedObjectTests.swift */; }; + EFF0DA2D3ABFA1D6AD7CE423953F0E1D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */; }; + F0AF237BAD0314FA61FC6C54DE9C6F02 /* UnitConvertable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 222111EB6500A946E4CCADB957300A19 /* UnitConvertable.swift */; }; + F116D8C6B1F2E58DCA4C16A9A83F034C /* HealthKitReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C7734C464098185A3DC8F3A784D58D /* HealthKitReader.swift */; }; + F283F24518E80B425D8D77E52C42B198 /* Extensions+HKActivitySummary.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C5CC536BD777F389D6C6B4F9C1CAFF /* Extensions+HKActivitySummary.swift */; }; + F425257EFC5840BCEC6D5F06D8486014 /* HealthKitReporterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B5A44750CB1C28DBB79D5FB395FCF59 /* HealthKitReporterTests.swift */; }; + F60CA6F500FE6715F82D126B0209BB4E /* Statistics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 276C0E1C96007154F3EB63D85D341CCD /* Statistics.swift */; }; + F745CE840F5AD69627586294E70BB9F7 /* DeletedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B06AD19CEC288C0886F873C782AAD11 /* DeletedObject.swift */; }; + F8216DB950418CF83DB9C687F0C1807D /* HealthKitManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFBFF2DDED0808E73F55AA6D99367596 /* HealthKitManager.swift */; }; + F8FFD22B85640666C33325AD78FFF0F3 /* WorkoutEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C47FE1F97CBF34F88CF449047E61FEB2 /* WorkoutEventTests.swift */; }; + FF065D19CB956B095A4377990E2715CB /* Pods-HealthKitReporter_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2810499E4BCD5F7A87DDBD10D478C248 /* Pods-HealthKitReporter_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 1D86DB38B43E80AB41E39090DE8582C7 /* PBXContainerItemProxy */ = { + A6CE1C26B06BBBE9E59867969C8F82A1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; remoteGlobalIDString = 5A02BB0F1AC44F7E176E662038412466; remoteInfo = HealthKitReporter; }; - 77B5177E471D03D84010CE70DB806746 /* PBXContainerItemProxy */ = { + A93A4E42D5FFC2252F13989652DF8556 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 28111CA3729B131600777B0AE0E0AF79; - remoteInfo = "Pods-HealthKitReporter_Example"; + remoteGlobalIDString = 5A02BB0F1AC44F7E176E662038412466; + remoteInfo = HealthKitReporter; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 040EFF0626E4C86C00D37F04 /* Extensions+HKCategoryValueAudioExposureEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueAudioExposureEvent.swift"; sourceTree = ""; }; - 040EFF0826E4C91700D37F04 /* Extensions+HKCategoryValueSleepAnalysis.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueSleepAnalysis.swift"; sourceTree = ""; }; - 040EFF0A26E4C97500D37F04 /* Extensions+HKCategoryValue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValue.swift"; sourceTree = ""; }; - 040EFF0C26E4C9A900D37F04 /* Extensions+HKCategoryValueMenstrualFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueMenstrualFlow.swift"; sourceTree = ""; }; - 040EFF0E26E4C9FB00D37F04 /* Extensions+HKCategoryValueOvulationTestResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueOvulationTestResult.swift"; sourceTree = ""; }; - 040EFF1026E4CA3600D37F04 /* Extensions+HKCategoryValueCervicalMucusQuality.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueCervicalMucusQuality.swift"; sourceTree = ""; }; - 040EFF1226E4CA6000D37F04 /* Extensions+HKCategoryValueAppleStandHour.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueAppleStandHour.swift"; sourceTree = ""; }; - 040EFF1426E4CAE200D37F04 /* Extensions+HKCategoryValueLowCardioFitnessEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueLowCardioFitnessEvent.swift"; sourceTree = ""; }; - 040EFF1626E4CB2500D37F04 /* Extensions+HKCategoryValueSeverity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueSeverity.swift"; sourceTree = ""; }; - 040EFF1826E4CB8700D37F04 /* Extensions+HKCategoryValuePresence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValuePresence.swift"; sourceTree = ""; }; - 040EFF1A26E4CBD800D37F04 /* Extensions+HKCategoryValueAppetiteChanges.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueAppetiteChanges.swift"; sourceTree = ""; }; - 040EFF1C26E4CC1500D37F04 /* Extensions+HKCategoryValueHeadphoneAudioExposureEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueHeadphoneAudioExposureEvent.swift"; sourceTree = ""; }; - 040EFF1E26E4CCCC00D37F04 /* Extensions+HKCategoryValueEnvironmentalAudioExposureEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueEnvironmentalAudioExposureEvent.swift"; sourceTree = ""; }; - 040EFF2026E4CD0500D37F04 /* Extensions+HKCategoryValueContraceptive.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueContraceptive.swift"; sourceTree = ""; }; - 0420239126178860001C40F7 /* Extensions+HKWorkoutConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+HKWorkoutConfiguration.swift"; sourceTree = ""; }; - 0420239226178860001C40F7 /* Extensions+HKBloodType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+HKBloodType.swift"; sourceTree = ""; }; - 0420239326178860001C40F7 /* Extensions+HKStatistics.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+HKStatistics.swift"; sourceTree = ""; }; - 0420239426178860001C40F7 /* Extensions+HKWorkoutActivityType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+HKWorkoutActivityType.swift"; sourceTree = ""; }; - 0420239526178860001C40F7 /* Extensions+String.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+String.swift"; sourceTree = ""; }; - 0420239626178860001C40F7 /* Extensions+HKCategoryType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryType.swift"; sourceTree = ""; }; - 0420239726178860001C40F7 /* Extensions+HKCorrelation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCorrelation.swift"; sourceTree = ""; }; - 0420239826178860001C40F7 /* Extensions+Double.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+Double.swift"; sourceTree = ""; }; - 0420239926178860001C40F7 /* Extensions+HKFitzpatrickSkinType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+HKFitzpatrickSkinType.swift"; sourceTree = ""; }; - 0420239A26178860001C40F7 /* Extensions+HKCategorySample.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategorySample.swift"; sourceTree = ""; }; - 0420239B26178860001C40F7 /* Extensions+HKActivitySummary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+HKActivitySummary.swift"; sourceTree = ""; }; - 0420239C26178860001C40F7 /* Extensions+HKElectrocardiogram.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+HKElectrocardiogram.swift"; sourceTree = ""; }; - 0420239D26178860001C40F7 /* Extensions+HKQuantityType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+HKQuantityType.swift"; sourceTree = ""; }; - 0420239E26178860001C40F7 /* Extensions+HKSample.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+HKSample.swift"; sourceTree = ""; }; - 0420239F26178860001C40F7 /* Extensions+NSPredicate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+NSPredicate.swift"; sourceTree = ""; }; - 042023A026178860001C40F7 /* Extensions+Encodable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+Encodable.swift"; sourceTree = ""; }; - 042023A126178860001C40F7 /* Extensions+HKWheelchairUse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+HKWheelchairUse.swift"; sourceTree = ""; }; - 042023A226178860001C40F7 /* Extensions+HKSourceRevision.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+HKSourceRevision.swift"; sourceTree = ""; }; - 042023A326178860001C40F7 /* Extensions+HKQuantitiySample.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+HKQuantitiySample.swift"; sourceTree = ""; }; - 042023A426178860001C40F7 /* Extensions+DateComponents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+DateComponents.swift"; sourceTree = ""; }; - 042023A526178860001C40F7 /* Extensions+Date.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+Date.swift"; sourceTree = ""; }; - 042023A626178860001C40F7 /* Extensions+HKWorkout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+HKWorkout.swift"; sourceTree = ""; }; - 042023A726178860001C40F7 /* Extensions+HKBiologicalSex.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+HKBiologicalSex.swift"; sourceTree = ""; }; - 042023A826178860001C40F7 /* Extensions+Dictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+Dictionary.swift"; sourceTree = ""; }; - 042023A926178860001C40F7 /* Extensions+HKWorkoutEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+HKWorkoutEvent.swift"; sourceTree = ""; }; - 042023AA26178860001C40F7 /* Extensions+HKActivityMoveMode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+HKActivityMoveMode.swift"; sourceTree = ""; }; - 042023AC26178860001C40F7 /* HealthKitObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HealthKitObserver.swift; sourceTree = ""; }; - 042023AD26178860001C40F7 /* HealthKitWriter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HealthKitWriter.swift; sourceTree = ""; }; - 042023AF26178860001C40F7 /* SeriesSampleRetriever.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SeriesSampleRetriever.swift; sourceTree = ""; }; - 042023B026178860001C40F7 /* ElectrocardiogramRetriever.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ElectrocardiogramRetriever.swift; sourceTree = ""; }; - 042023B126178860001C40F7 /* HealthKitReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HealthKitReader.swift; sourceTree = ""; }; - 042023B226178860001C40F7 /* HealthKitManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HealthKitManager.swift; sourceTree = ""; }; - 042023B626178860001C40F7 /* Source.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Source.swift; sourceTree = ""; }; - 042023B726178860001C40F7 /* Statistics.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Statistics.swift; sourceTree = ""; }; - 042023B826178860001C40F7 /* Workout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Workout.swift; sourceTree = ""; }; - 042023B926178860001C40F7 /* Correlation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Correlation.swift; sourceTree = ""; }; - 042023BA26178860001C40F7 /* Sample.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Sample.swift; sourceTree = ""; }; - 042023BB26178860001C40F7 /* Quantity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Quantity.swift; sourceTree = ""; }; - 042023BC26178860001C40F7 /* WorkoutRoute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WorkoutRoute.swift; sourceTree = ""; }; - 042023BD26178860001C40F7 /* DeletedObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeletedObject.swift; sourceTree = ""; }; - 042023BE26178860001C40F7 /* Electrocardiogram.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Electrocardiogram.swift; sourceTree = ""; }; - 042023BF26178860001C40F7 /* WorkoutEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WorkoutEvent.swift; sourceTree = ""; }; - 042023C026178860001C40F7 /* ActivitySummary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActivitySummary.swift; sourceTree = ""; }; - 042023C126178860001C40F7 /* Category.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Category.swift; sourceTree = ""; }; - 042023C226178860001C40F7 /* Identifiable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Identifiable.swift; sourceTree = ""; }; - 042023C326178860001C40F7 /* Device.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Device.swift; sourceTree = ""; }; - 042023C426178860001C40F7 /* WorkoutConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WorkoutConfiguration.swift; sourceTree = ""; }; - 042023C526178860001C40F7 /* Characteristic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Characteristic.swift; sourceTree = ""; }; - 042023C626178860001C40F7 /* SourceRevision.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SourceRevision.swift; sourceTree = ""; }; - 042023C726178860001C40F7 /* Original.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Original.swift; sourceTree = ""; }; - 042023C826178860001C40F7 /* UnitConvertable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnitConvertable.swift; sourceTree = ""; }; - 042023CA26178860001C40F7 /* CharacteristicType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CharacteristicType.swift; sourceTree = ""; }; - 042023CB26178860001C40F7 /* ActivitySummaryType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActivitySummaryType.swift; sourceTree = ""; }; - 042023CD26178860001C40F7 /* QuantityType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuantityType.swift; sourceTree = ""; }; - 042023CE26178860001C40F7 /* CategoryType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CategoryType.swift; sourceTree = ""; }; - 042023CF26178860001C40F7 /* SeriesType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SeriesType.swift; sourceTree = ""; }; - 042023D026178860001C40F7 /* ElectrocardiogramType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ElectrocardiogramType.swift; sourceTree = ""; }; - 042023D126178860001C40F7 /* SampleType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SampleType.swift; sourceTree = ""; }; - 042023D226178860001C40F7 /* DocumentType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DocumentType.swift; sourceTree = ""; }; - 042023D326178860001C40F7 /* WorkoutType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WorkoutType.swift; sourceTree = ""; }; - 042023D426178860001C40F7 /* CorrelationType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CorrelationType.swift; sourceTree = ""; }; - 042023D526178860001C40F7 /* ObjectType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectType.swift; sourceTree = ""; }; - 042023D626178860001C40F7 /* Payload.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Payload.swift; sourceTree = ""; }; - 042023D726178860001C40F7 /* UpdateFrequency.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdateFrequency.swift; sourceTree = ""; }; - 042023D826178860001C40F7 /* Harmonizable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Harmonizable.swift; sourceTree = ""; }; - 042023D926178860001C40F7 /* PreferredUnit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferredUnit.swift; sourceTree = ""; }; - 042023DA26178860001C40F7 /* HealthKitError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HealthKitError.swift; path = Sources/HealthKitError.swift; sourceTree = ""; }; - 042023DB26178860001C40F7 /* HealthKitReporter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HealthKitReporter.swift; path = Sources/HealthKitReporter.swift; sourceTree = ""; }; - 04CC38E326E37F970067ABFD /* Extensions+HKWorkoutEventType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+HKWorkoutEventType.swift"; sourceTree = ""; }; - 04F6E1752715D6B800A63807 /* HeartbeatSeries.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeartbeatSeries.swift; sourceTree = ""; }; - 04F6E1772715DADC00A63807 /* Extensions+HKHeartbeatSeriesSample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extensions+HKHeartbeatSeriesSample.swift"; sourceTree = ""; }; - 0CBCDB9707C28427FF60B97538188EDE /* Pods_HealthKitReporter_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_HealthKitReporter_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 021777A613B44D20DDCE3CA6CFED76E4 /* Electrocardiogram.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Electrocardiogram.swift; sourceTree = ""; }; + 04FBB513B464D9F96552E98FAE1343BF /* Category.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Category.swift; sourceTree = ""; }; + 09A91F461B623281D4F426E925D6B6BE /* HealthKitReporter.unit-tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "HealthKitReporter.unit-tests.debug.xcconfig"; sourceTree = ""; }; + 0CBCDB9707C28427FF60B97538188EDE /* Pods-HealthKitReporter_Example */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-HealthKitReporter_Example"; path = Pods_HealthKitReporter_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 101CB243B88135DF695DCD79346E7AEF /* DeletedObjectTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DeletedObjectTests.swift; path = Tests/DeletedObjectTests.swift; sourceTree = ""; }; + 106F1D0F830265A82D691E1B3C0C316C /* Extensions+HKCategoryValueEnvironmentalAudioExposureEvent.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueEnvironmentalAudioExposureEvent.swift"; sourceTree = ""; }; 10ED9239B0ED1C13D65048DF6C2EDD88 /* Pods-HealthKitReporter_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-HealthKitReporter_Example.release.xcconfig"; sourceTree = ""; }; - 1418EAB84877F65C010D2DD616A65D44 /* HealthKitReporter-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "HealthKitReporter-umbrella.h"; sourceTree = ""; }; - 1716C45425278E190037EA4E /* CHANGELOG.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = ""; }; - 17CD92EF255C095B00F3CD09 /* build_script.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = build_script.sh; sourceTree = ""; }; + 14EAB9F96C66944F221F1658FD262635 /* Identifiable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Identifiable.swift; sourceTree = ""; }; 19106C382C9023657C61D1BE14E407E2 /* Pods-HealthKitReporter_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-HealthKitReporter_Tests.modulemap"; sourceTree = ""; }; - 27617830750DC147AFDBE7EA9D445C3A /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + 198D71D3AF21150E7A31E171D9847E1E /* CharacteristicTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CharacteristicTests.swift; path = Tests/CharacteristicTests.swift; sourceTree = ""; }; + 1B5A44750CB1C28DBB79D5FB395FCF59 /* HealthKitReporterTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HealthKitReporterTests.swift; path = Tests/HealthKitReporterTests.swift; sourceTree = ""; }; + 1DA81DC75879F428CC7DD41B6ABAE326 /* HealthKitReporter.unit-tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "HealthKitReporter.unit-tests.release.xcconfig"; sourceTree = ""; }; + 1DEFD53A33731860ACED9D7FDC45A703 /* Payload.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Payload.swift; sourceTree = ""; }; + 222111EB6500A946E4CCADB957300A19 /* UnitConvertable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = UnitConvertable.swift; sourceTree = ""; }; + 276C0E1C96007154F3EB63D85D341CCD /* Statistics.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Statistics.swift; sourceTree = ""; }; 2810499E4BCD5F7A87DDBD10D478C248 /* Pods-HealthKitReporter_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-HealthKitReporter_Example-umbrella.h"; sourceTree = ""; }; - 3212113385A8FBBDB272BD23C409FF61 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - 3437F34D44A783E1EFFA682E39474B09 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; - 3893D52BF738F0CD1893DBF22997BD58 /* HealthKitReporter.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = HealthKitReporter.modulemap; sourceTree = ""; }; - 414D7DD0DA5581301732C4FA52D8A2E7 /* HealthKitReporter.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = HealthKitReporter.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 285279B6B26D290EA701D3EC4966C088 /* Extensions+HKFitzpatrickSkinType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKFitzpatrickSkinType.swift"; sourceTree = ""; }; + 2977D7A51AC617CDFE96F27412486B8D /* Extensions+HKWorkoutEvent.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKWorkoutEvent.swift"; sourceTree = ""; }; + 2D09718B54ED3E490683579AA4C5D5F9 /* Extensions+HKCategoryType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryType.swift"; sourceTree = ""; }; + 2E1E2342E262E1503D3E8EA5D9144B70 /* WorkoutRoute.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WorkoutRoute.swift; sourceTree = ""; }; + 3102A396ED211624C89742DC1A2DB605 /* Extensions+HKBloodType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKBloodType.swift"; sourceTree = ""; }; + 355655E0A1867FAA9D1FAFD4FABB7F4C /* Source.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Source.swift; sourceTree = ""; }; + 38CA3DC113C54083F304FF7EEF4E9068 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; + 39C648D3DC1753ED463E13801E3D76AD /* HealthKitReporter.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = HealthKitReporter.release.xcconfig; sourceTree = ""; }; + 3AEA8093D9225C79AA3F1A0C3DB4AC54 /* Extensions+String.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+String.swift"; sourceTree = ""; }; + 3CA4849040BD152BBA56AB34E8712EDB /* Extensions+HKCategoryValuePresence.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValuePresence.swift"; sourceTree = ""; }; + 3D69270819100EAB8BDBF1A42474EDED /* Device.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Device.swift; sourceTree = ""; }; + 3DA80F32525A8BDE69FA77E6CB72B5BE /* WorkoutConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WorkoutConfiguration.swift; sourceTree = ""; }; + 3DAC7CB4A7DBBBA1D3242C5A8790A749 /* Harmonizable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Harmonizable.swift; sourceTree = ""; }; + 414D7DD0DA5581301732C4FA52D8A2E7 /* HealthKitReporter */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = HealthKitReporter; path = HealthKitReporter.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 44193B23B1FADB45496E1AA11C5B3002 /* Pods-HealthKitReporter_Tests-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-HealthKitReporter_Tests-Info.plist"; sourceTree = ""; }; + 44545002736B1F05EECB221CEBFAE961 /* ActivitySummaryType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ActivitySummaryType.swift; sourceTree = ""; }; + 48F38C03BC9C922F42622F968658E132 /* Extensions+HKActivityMoveMode.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKActivityMoveMode.swift"; sourceTree = ""; }; + 49D05D7B03F3832E1AEB9C0DE45A27CA /* HealthKitReporter-Unit-Tests-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "HealthKitReporter-Unit-Tests-Info.plist"; sourceTree = ""; }; + 49E4CCB9A739C5D6C44E6FDE3CBA336A /* HeartbeatSeries.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HeartbeatSeries.swift; sourceTree = ""; }; 4B41AA02842340FAE870ED55A3E10581 /* Pods-HealthKitReporter_Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-HealthKitReporter_Tests-acknowledgements.markdown"; sourceTree = ""; }; - 4F7AB517F06E1D1713499728AC55C83C /* HealthKitReporter-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "HealthKitReporter-dummy.m"; sourceTree = ""; }; - 50AA0CA84AA46A85BDCFA91A07CA472E /* HealthKitReporter.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = HealthKitReporter.release.xcconfig; sourceTree = ""; }; + 4BD29D23F901C237B31A5D692F9D9713 /* ObjectType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ObjectType.swift; sourceTree = ""; }; + 4F203E555184E35EAAD3AD87D89D271B /* HealthKitReporter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HealthKitReporter.swift; path = Sources/HealthKitReporter.swift; sourceTree = ""; }; + 4F465225C97C1D55104FE46F280F9740 /* Quantity.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Quantity.swift; sourceTree = ""; }; 54E896CEBBB0F7AB51775AD8DB2A3240 /* Pods-HealthKitReporter_Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-HealthKitReporter_Tests-umbrella.h"; sourceTree = ""; }; - 620026A50D6F3042580BA62B0F2A5E24 /* HealthKitReporter.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = HealthKitReporter.debug.xcconfig; sourceTree = ""; }; - 71D8BEAF4ADFF6BB7D99C7D261B03A10 /* Pods_HealthKitReporter_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_HealthKitReporter_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 5E295CBB228A75CA020C76C2067BF4C7 /* ActivitySummaryTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ActivitySummaryTests.swift; path = Tests/ActivitySummaryTests.swift; sourceTree = ""; }; + 5E4CB548A95CBF4A96C788AF488B22EA /* Extensions+HKCategoryValuePregnancyTestResult.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValuePregnancyTestResult.swift"; sourceTree = ""; }; + 5FCDDDC9653ECC45320F6CFA3DAF8A4A /* Extensions+HKCategoryValueProgesteroneTestResult.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueProgesteroneTestResult.swift"; sourceTree = ""; }; + 60CF485456A867C21161376D061AA225 /* HealthKitError.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HealthKitError.swift; path = Sources/HealthKitError.swift; sourceTree = ""; }; + 65F22F9819EE157ADFD08520D456C6A4 /* Original.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Original.swift; sourceTree = ""; }; + 67E73DDC6B7FB70C6BC6A76DD7AD0C93 /* Extensions+HKQuantitiySample.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKQuantitiySample.swift"; sourceTree = ""; }; + 67FC5BA46B00F310A4C8F9DA5DA7B9E8 /* ElectrocardiogramType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ElectrocardiogramType.swift; sourceTree = ""; }; + 6AA24F0D87CCAC22B1512D722F8B81C1 /* Extensions+NSPredicate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+NSPredicate.swift"; sourceTree = ""; }; + 6B508D98C4C56C97BDB8D0D1BB46E38F /* PreferredUnit.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PreferredUnit.swift; sourceTree = ""; }; + 6B8A9E7706067AF7560F39C291BEE3AC /* Extensions+HKCategoryValue.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValue.swift"; sourceTree = ""; }; + 6DF381181DC7BCFFB41F309825BF2D06 /* Extensions+HKElectrocardiogram.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKElectrocardiogram.swift"; sourceTree = ""; }; + 6F13D5F3D30DFF2CB1E1967820E6546A /* Extensions+HKCategoryValueSleepAnalysis.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueSleepAnalysis.swift"; sourceTree = ""; }; + 71D8BEAF4ADFF6BB7D99C7D261B03A10 /* Pods-HealthKitReporter_Tests */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-HealthKitReporter_Tests"; path = Pods_HealthKitReporter_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 725EEB8C2CE54A8A15BDD5F3DB916AB3 /* Extensions+Date.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+Date.swift"; sourceTree = ""; }; + 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 7354B0B62C6293B4005297E1 /* ClinicalType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClinicalType.swift; sourceTree = ""; }; + 7354B0B82C629433005297E1 /* Extensions+HKClinicalRecord.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Extensions+HKClinicalRecord.swift"; sourceTree = ""; }; + 7354B0BC2C62945F005297E1 /* ClinicalRecord.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClinicalRecord.swift; sourceTree = ""; }; + 7614D1074DB0BD9144DC75E02B319E09 /* StatisticsTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StatisticsTests.swift; path = Tests/StatisticsTests.swift; sourceTree = ""; }; 775C0010DC236F50A09CDEE5E5B878F4 /* Pods-HealthKitReporter_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-HealthKitReporter_Tests-dummy.m"; sourceTree = ""; }; + 779D0EE7F0734A26C238E0380C189EC2 /* Extensions+HKCategoryValueAppleWalkingSteadinessEvent.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueAppleWalkingSteadinessEvent.swift"; sourceTree = ""; }; + 7835AED3290DA39000D9CB35 /* Metadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Metadata.swift; sourceTree = ""; }; + 7C35147CFB0794752DC14C3CAC878E0F /* Extensions+HKVisionPrescriptionType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKVisionPrescriptionType.swift"; sourceTree = ""; }; + 7F9C1D2DC980211C3F4641DE18E0D0F7 /* DeviceTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DeviceTests.swift; path = Tests/DeviceTests.swift; sourceTree = ""; }; + 8155DF4384A333207865B8FB24B9D8AA /* Extensions+HKCategoryValueAppetiteChanges.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueAppetiteChanges.swift"; sourceTree = ""; }; + 82063CBFA5BA4A9FFAD96EC80564B6EF /* Extensions+HKHeartbeatSeriesSample.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKHeartbeatSeriesSample.swift"; sourceTree = ""; }; + 822BE42AD8A5F44EFA02C8B679535B70 /* Extensions+HKWheelchairUse.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKWheelchairUse.swift"; sourceTree = ""; }; + 83D631E02E31514291F7514D4E6A382A /* HealthKitReporter-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "HealthKitReporter-Info.plist"; sourceTree = ""; }; + 843D457EC25CABF71EBFA5B80912C088 /* HealthKitWriter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HealthKitWriter.swift; sourceTree = ""; }; + 84F2596E09A7D67E6EDBD73E42B8FFCA /* Extensions+DateComponents.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+DateComponents.swift"; sourceTree = ""; }; + 850D6A69E2DC43940596668A9534251E /* Extensions+HKCategoryValueLowCardioFitnessEvent.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueLowCardioFitnessEvent.swift"; sourceTree = ""; }; 859C0FD784EA382944470E55EC51F72F /* Pods-HealthKitReporter_Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-HealthKitReporter_Tests-acknowledgements.plist"; sourceTree = ""; }; + 8671054852BAA6C7E7CC6C86B5002C7F /* VisionPrescription.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = VisionPrescription.swift; sourceTree = ""; }; + 87DB34BFBC9BF8162EBD02D5C6D298C3 /* CharacteristicType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CharacteristicType.swift; sourceTree = ""; }; + 884CF18D0A5BA4159D6BD793F9F1BC6F /* Extensions+HKCorrelation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCorrelation.swift"; sourceTree = ""; }; + 88988A956142E177BE9C9C195EE79691 /* Extensions+Double.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+Double.swift"; sourceTree = ""; }; + 88FBE9056A11F9DCE6CAEA1B354BAF9F /* HealthKitReporter.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; path = HealthKitReporter.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 8B06AD19CEC288C0886F873C782AAD11 /* DeletedObject.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DeletedObject.swift; sourceTree = ""; }; + 8BD8270979E130D9007CC7FFA74E2407 /* Extensions+HKWorkoutEventType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKWorkoutEventType.swift"; sourceTree = ""; }; + 8D97E81B98A909D030B0362B21F0DD50 /* Extensions+HKQuantityType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKQuantityType.swift"; sourceTree = ""; }; + 908029735F55FEA9CACDB0D1A7D54496 /* UpdateFrequency.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = UpdateFrequency.swift; sourceTree = ""; }; + 921DD3F31C4FBB5AE97A65943317407E /* HealthKitReporter-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "HealthKitReporter-dummy.m"; sourceTree = ""; }; 9602EB29FFFC99DDBC1B33C58FBA8B04 /* Pods-HealthKitReporter_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-HealthKitReporter_Example-frameworks.sh"; sourceTree = ""; }; + 9614D2031F58F5E6672FA11E73049B17 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + 96183C6EFBB56F5D2AE474F39E897793 /* WorkoutType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WorkoutType.swift; sourceTree = ""; }; 989097361B77629199333A71012885BA /* Pods-HealthKitReporter_Example-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-HealthKitReporter_Example-Info.plist"; sourceTree = ""; }; - 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; }; + 98AF73ECB6BABADE8B248920630A75CF /* SourceRevision.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SourceRevision.swift; sourceTree = ""; }; + 9AB9C2D8B500080A5420C0810894C5E4 /* Extensions+HKSample.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKSample.swift"; sourceTree = ""; }; + 9B080F197C40B7ACE4394268D1CDBC6A /* HealthKitReporter-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "HealthKitReporter-umbrella.h"; sourceTree = ""; }; + 9C160DDC8F72F8216539DE0DC7E0C1A6 /* Extensions+HKWorkout.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKWorkout.swift"; sourceTree = ""; }; + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 9DA4445FA0413B69A507EE04B90E310E /* Correlation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Correlation.swift; sourceTree = ""; }; + 9DDE7FCD8E64573651E4D6FA92385669 /* HealthKitReporter-Unit-Tests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "HealthKitReporter-Unit-Tests-frameworks.sh"; sourceTree = ""; }; + 9F8156E71A7309B2C760AEE3BCB535F4 /* Extensions+HKCategoryValueMenstrualFlow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueMenstrualFlow.swift"; sourceTree = ""; }; + 9FFDBE6EB771F9C6CA4167E336AF7A87 /* Sample.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Sample.swift; sourceTree = ""; }; + A393395C8707BD18CA7E2D5CF3FE4822 /* Extensions+HKStatistics.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKStatistics.swift"; sourceTree = ""; }; + A6CCC81EA5C6B1365AA83E14BA201559 /* QuantityType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = QuantityType.swift; sourceTree = ""; }; + AA110780BB027D6B81BD60D0C560AFFA /* Extensions+Encodable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+Encodable.swift"; sourceTree = ""; }; + AA742DEAB1A5A59D4E6C6865DAA33748 /* HealthKitReporter-Unit-Tests-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "HealthKitReporter-Unit-Tests-prefix.pch"; sourceTree = ""; }; + AA77ED0476C73CBFC08F47BF12D6D1E9 /* Extensions+HKCategoryValueCervicalMucusQuality.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueCervicalMucusQuality.swift"; sourceTree = ""; }; + AC2D54E14A48876FEF4AB7FC0D65A027 /* Workout.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Workout.swift; sourceTree = ""; }; + ACD4232F0A2B118D033985000AD5D0CB /* Extensions+HKCategoryValueOvulationTestResult.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueOvulationTestResult.swift"; sourceTree = ""; }; + B00A32093EC52BD97BC9CD2DE792DBD4 /* Extensions+HKCategoryValueAppleStandHour.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueAppleStandHour.swift"; sourceTree = ""; }; + B0C5308EDBE4A3479D38CB48FCA95B94 /* Extensions+HKBiologicalSex.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKBiologicalSex.swift"; sourceTree = ""; }; + B1B657204828C2E3722C952AD326C255 /* QuantityTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = QuantityTests.swift; path = Tests/QuantityTests.swift; sourceTree = ""; }; + B39A807B10BADAA7683C62A54AE2F1DF /* SeriesType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SeriesType.swift; sourceTree = ""; }; B4665EC9F0AB7C6F5920DFFC6369A299 /* Pods-HealthKitReporter_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-HealthKitReporter_Tests.release.xcconfig"; sourceTree = ""; }; + B7389FA911D6AAD9522A038D7CAA3770 /* Characteristic.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Characteristic.swift; sourceTree = ""; }; + B8BFD5719C667AF1C203A2A09A771312 /* WorkoutTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = WorkoutTests.swift; path = Tests/WorkoutTests.swift; sourceTree = ""; }; + B90113B9E28C8E17E86F0B0F1FBF6898 /* ElectrocardiogramRetriever.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ElectrocardiogramRetriever.swift; sourceTree = ""; }; + B983E73004D5D8DDF1A18C149EA2EED5 /* SourceRevisionTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SourceRevisionTests.swift; path = Tests/SourceRevisionTests.swift; sourceTree = ""; }; BA526D72C16C6C80D67D285E6CE11803 /* Pods-HealthKitReporter_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-HealthKitReporter_Example.modulemap"; sourceTree = ""; }; - BFA0D072B8047DA9E144F9E577A0E8C7 /* HealthKitReporter-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "HealthKitReporter-prefix.pch"; sourceTree = ""; }; + BA8B062B4C30F0E7B9F7122282C803A1 /* HealthKitReporter-Unit-Tests */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = "HealthKitReporter-Unit-Tests"; path = "HealthKitReporter-Unit-Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + BBBD3A4D4F856461FEDF0C9BD870F1D0 /* SourceTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SourceTests.swift; path = Tests/SourceTests.swift; sourceTree = ""; }; + BF9C8313AFF8190CEDAE726029E26604 /* HealthKitObserver.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HealthKitObserver.swift; sourceTree = ""; }; + BFBFF2DDED0808E73F55AA6D99367596 /* HealthKitManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HealthKitManager.swift; sourceTree = ""; }; C0EC02AC4B15CC5111FCF6837D0734DB /* Pods-HealthKitReporter_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-HealthKitReporter_Example-acknowledgements.markdown"; sourceTree = ""; }; C1DF9C7E917631DB50FD5DEDE8CDA43A /* Pods-HealthKitReporter_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-HealthKitReporter_Example.debug.xcconfig"; sourceTree = ""; }; - D0323F7CE3BC4360566D5381CF38EDED /* HealthKitReporter-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "HealthKitReporter-Info.plist"; sourceTree = ""; }; + C1F2F3C0D5878CC84A0A2608512482CB /* Extensions+HKWorkoutConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKWorkoutConfiguration.swift"; sourceTree = ""; }; + C36CEC51B9FF98870F6847C451B710FA /* Extensions+Dictionary.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+Dictionary.swift"; sourceTree = ""; }; + C3C5CC536BD777F389D6C6B4F9C1CAFF /* Extensions+HKActivitySummary.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKActivitySummary.swift"; sourceTree = ""; }; + C47FE1F97CBF34F88CF449047E61FEB2 /* WorkoutEventTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = WorkoutEventTests.swift; path = Tests/WorkoutEventTests.swift; sourceTree = ""; }; + C51C0F692BD912CE07C795C872381A68 /* CorrelationTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CorrelationTests.swift; path = Tests/CorrelationTests.swift; sourceTree = ""; }; + C7114076D9A9EBCD319323158DACCB3B /* SampleType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SampleType.swift; sourceTree = ""; }; + C8C7734C464098185A3DC8F3A784D58D /* HealthKitReader.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HealthKitReader.swift; sourceTree = ""; }; + CA30DC80B6382A498E796CBFBC0355E5 /* ElectrocardiogramTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ElectrocardiogramTests.swift; path = Tests/ElectrocardiogramTests.swift; sourceTree = ""; }; + CCD513890913592D2CC8AEAA4A52A42D /* HeartbeatSeriesTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HeartbeatSeriesTests.swift; path = Tests/HeartbeatSeriesTests.swift; sourceTree = ""; }; + D0C024B54024A1874B482C78F65CC70A /* Extensions+HKWorkoutActivityType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKWorkoutActivityType.swift"; sourceTree = ""; }; + D17B2FDE0B6D0320BE2EB63FF8E7C28C /* CorrelationType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CorrelationType.swift; sourceTree = ""; }; + D23E54060150E4FF1128E7B1BE26ED26 /* CategoryTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CategoryTests.swift; path = Tests/CategoryTests.swift; sourceTree = ""; }; + D2F7E69DFF38A7DCAD305271E21E7B66 /* Extensions+HKCategoryValueHeadphoneAudioExposureEvent.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueHeadphoneAudioExposureEvent.swift"; sourceTree = ""; }; D4755EC74B169D2FA28AC646D8EE2033 /* Pods-HealthKitReporter_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-HealthKitReporter_Tests.debug.xcconfig"; sourceTree = ""; }; + D95556BAE1B44A602CBAA93EDD3BB464 /* CategoryType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CategoryType.swift; sourceTree = ""; }; + DAAC829BB74B370CC624B2BF0FB92560 /* DocumentType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DocumentType.swift; sourceTree = ""; }; DBB4C8B104BDB5BB5ABE67400176B082 /* Pods-HealthKitReporter_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-HealthKitReporter_Example-dummy.m"; sourceTree = ""; }; + DD811C573A49E507F0A87C150AE3AF32 /* Extensions+HKWorkoutRoute.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKWorkoutRoute.swift"; sourceTree = ""; }; + DEAD47E57F8ECF25A1220E65DFAB46B3 /* HealthKitReporter.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = HealthKitReporter.modulemap; sourceTree = ""; }; + E0C1816183E171B9EB7ACB57947D6715 /* SeriesSampleRetriever.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SeriesSampleRetriever.swift; sourceTree = ""; }; + E126ADB64FCC998644BE8A1F2EA58259 /* Extensions+HKCategoryValueContraceptive.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueContraceptive.swift"; sourceTree = ""; }; + E2DCB207B3C0C062B28F5EE3DBFB4B7B /* VisionPrescriptionType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = VisionPrescriptionType.swift; sourceTree = ""; }; + E32F57F22FDB65E7823F8D10B88C959A /* WorkoutRouteTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = WorkoutRouteTests.swift; path = Tests/WorkoutRouteTests.swift; sourceTree = ""; }; E58E764D298A13A6D23E438089A52F4D /* Pods-HealthKitReporter_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-HealthKitReporter_Example-acknowledgements.plist"; sourceTree = ""; }; - E66BFAA856AE9B9B4C90D91FC25EDC39 /* HealthKitReporter.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; path = HealthKitReporter.podspec; sourceTree = ""; tabWidth = 2; }; + E7A8940EF42B5DB48394C8EEC564DDD2 /* Extensions+HKCategoryValueAudioExposureEvent.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueAudioExposureEvent.swift"; sourceTree = ""; }; + EECFB79FD2730DB471F3DB655747E03B /* Extensions+HKCategoryValueSeverity.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategoryValueSeverity.swift"; sourceTree = ""; }; + EED4C86C81FD5948A1AD11F9C4446C54 /* Extensions+HKVisionPrescription.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKVisionPrescription.swift"; sourceTree = ""; }; + F24DB46EFB8B2ADE86C9B96CA26545B5 /* WorkoutConfigurationTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = WorkoutConfigurationTests.swift; path = Tests/WorkoutConfigurationTests.swift; sourceTree = ""; }; + F47BE8DAC9541A04DE27C3D911D7B6F7 /* HealthKitReporter-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "HealthKitReporter-prefix.pch"; sourceTree = ""; }; + F5D11E89F4AA8A564655156AD5D4F8F2 /* Extensions+HKCategorySample.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKCategorySample.swift"; sourceTree = ""; }; + F84D25CD6B9F6BE671048EA498BCD092 /* WorkoutEvent.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WorkoutEvent.swift; sourceTree = ""; }; + FA34A422D5D91CA343375D9F5656E0C9 /* HealthKitReporter.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = HealthKitReporter.debug.xcconfig; sourceTree = ""; }; + FAF5FC29558E97773504BFB7A6E3F0B7 /* ActivitySummary.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ActivitySummary.swift; sourceTree = ""; }; + FBC7718A4D411B5E691FCAAE7FD47FEF /* Extensions+HKSourceRevision.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Extensions+HKSourceRevision.swift"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 33EEEC7E47F8E6522CCF9B17C6BFA274 /* Frameworks */ = { + 11D0F81C30BB0297F53AD8C3FE961499 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 1050D86C275F823332DB71B3081511F3 /* Foundation.framework in Frameworks */, + D42E72FF3A0C160E1064077C62E7975D /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 4D04B966B9E84405230AFE63FF6C8124 /* Frameworks */ = { + 336CC995EA629F3CE34C679CC728F944 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - D679FAEC8D57E3786E2520FA2A1B9307 /* Foundation.framework in Frameworks */, + C23D7A7BF7D6947B2450C5E6B31C435C /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 696BAA608A18B81E1A6BA5A183C9B0AE /* Frameworks */ = { + 5F82A00BC1398E73D9C07FDE67F87B2A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 9EF9A02EEE3BA943B259F5CE9469FEF2 /* Foundation.framework in Frameworks */, + EFF0DA2D3ABFA1D6AD7CE423953F0E1D /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 80BA64646C59D79FFB9E5A948E6FF63E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6F9BC1C06ED9A7B5662C0AE96147598E /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 0420239026178860001C40F7 /* Decorator */ = { + 14DA66AAA298CA130F83EDADA52B6D5E /* HealthKitReporter */ = { isa = PBXGroup; children = ( - 0420239126178860001C40F7 /* Extensions+HKWorkoutConfiguration.swift */, - 0420239226178860001C40F7 /* Extensions+HKBloodType.swift */, - 0420239326178860001C40F7 /* Extensions+HKStatistics.swift */, - 0420239426178860001C40F7 /* Extensions+HKWorkoutActivityType.swift */, - 0420239526178860001C40F7 /* Extensions+String.swift */, - 0420239626178860001C40F7 /* Extensions+HKCategoryType.swift */, - 0420239726178860001C40F7 /* Extensions+HKCorrelation.swift */, - 0420239826178860001C40F7 /* Extensions+Double.swift */, - 0420239926178860001C40F7 /* Extensions+HKFitzpatrickSkinType.swift */, - 0420239A26178860001C40F7 /* Extensions+HKCategorySample.swift */, - 040EFF1826E4CB8700D37F04 /* Extensions+HKCategoryValuePresence.swift */, - 040EFF1426E4CAE200D37F04 /* Extensions+HKCategoryValueLowCardioFitnessEvent.swift */, - 0420239B26178860001C40F7 /* Extensions+HKActivitySummary.swift */, - 0420239C26178860001C40F7 /* Extensions+HKElectrocardiogram.swift */, - 0420239D26178860001C40F7 /* Extensions+HKQuantityType.swift */, - 0420239E26178860001C40F7 /* Extensions+HKSample.swift */, - 0420239F26178860001C40F7 /* Extensions+NSPredicate.swift */, - 042023A026178860001C40F7 /* Extensions+Encodable.swift */, - 042023A126178860001C40F7 /* Extensions+HKWheelchairUse.swift */, - 042023A226178860001C40F7 /* Extensions+HKSourceRevision.swift */, - 042023A326178860001C40F7 /* Extensions+HKQuantitiySample.swift */, - 042023A426178860001C40F7 /* Extensions+DateComponents.swift */, - 042023A526178860001C40F7 /* Extensions+Date.swift */, - 042023A626178860001C40F7 /* Extensions+HKWorkout.swift */, - 042023A726178860001C40F7 /* Extensions+HKBiologicalSex.swift */, - 042023A826178860001C40F7 /* Extensions+Dictionary.swift */, - 04CC38E326E37F970067ABFD /* Extensions+HKWorkoutEventType.swift */, - 042023A926178860001C40F7 /* Extensions+HKWorkoutEvent.swift */, - 042023AA26178860001C40F7 /* Extensions+HKActivityMoveMode.swift */, - 040EFF0626E4C86C00D37F04 /* Extensions+HKCategoryValueAudioExposureEvent.swift */, - 040EFF0826E4C91700D37F04 /* Extensions+HKCategoryValueSleepAnalysis.swift */, - 040EFF0A26E4C97500D37F04 /* Extensions+HKCategoryValue.swift */, - 040EFF0C26E4C9A900D37F04 /* Extensions+HKCategoryValueMenstrualFlow.swift */, - 040EFF0E26E4C9FB00D37F04 /* Extensions+HKCategoryValueOvulationTestResult.swift */, - 040EFF1026E4CA3600D37F04 /* Extensions+HKCategoryValueCervicalMucusQuality.swift */, - 040EFF1226E4CA6000D37F04 /* Extensions+HKCategoryValueAppleStandHour.swift */, - 040EFF1626E4CB2500D37F04 /* Extensions+HKCategoryValueSeverity.swift */, - 040EFF1A26E4CBD800D37F04 /* Extensions+HKCategoryValueAppetiteChanges.swift */, - 040EFF1C26E4CC1500D37F04 /* Extensions+HKCategoryValueHeadphoneAudioExposureEvent.swift */, - 040EFF1E26E4CCCC00D37F04 /* Extensions+HKCategoryValueEnvironmentalAudioExposureEvent.swift */, - 040EFF2026E4CD0500D37F04 /* Extensions+HKCategoryValueContraceptive.swift */, - 04F6E1772715DADC00A63807 /* Extensions+HKHeartbeatSeriesSample.swift */, + 60CF485456A867C21161376D061AA225 /* HealthKitError.swift */, + 4F203E555184E35EAAD3AD87D89D271B /* HealthKitReporter.swift */, + D092319D1ED8522122BAC9CBE6A5C206 /* Decorator */, + 99288F870A92ECAD92DAE0C7982CDF9A /* Model */, + D55E7EFACDC02B74FAE6B9F24FE9C4B0 /* Pod */, + D92E6A4864959C0B5145E94C3F8D8AC1 /* Service */, + D94EAC2CB68BFA623930C1B634294D1E /* Support Files */, + D585A22F16355D1647D19C8483AF6A81 /* Tests */, ); - name = Decorator; - path = Sources/Decorator; + name = HealthKitReporter; + path = ../..; sourceTree = ""; }; - 042023AB26178860001C40F7 /* Service */ = { + 1B4D5707885DF5F6A16D9EB25EC9D18E /* Pods-HealthKitReporter_Example */ = { isa = PBXGroup; children = ( - 042023AC26178860001C40F7 /* HealthKitObserver.swift */, - 042023AD26178860001C40F7 /* HealthKitWriter.swift */, - 042023B126178860001C40F7 /* HealthKitReader.swift */, - 042023B226178860001C40F7 /* HealthKitManager.swift */, - 042023AE26178860001C40F7 /* Retriever */, + BA526D72C16C6C80D67D285E6CE11803 /* Pods-HealthKitReporter_Example.modulemap */, + C0EC02AC4B15CC5111FCF6837D0734DB /* Pods-HealthKitReporter_Example-acknowledgements.markdown */, + E58E764D298A13A6D23E438089A52F4D /* Pods-HealthKitReporter_Example-acknowledgements.plist */, + DBB4C8B104BDB5BB5ABE67400176B082 /* Pods-HealthKitReporter_Example-dummy.m */, + 9602EB29FFFC99DDBC1B33C58FBA8B04 /* Pods-HealthKitReporter_Example-frameworks.sh */, + 989097361B77629199333A71012885BA /* Pods-HealthKitReporter_Example-Info.plist */, + 2810499E4BCD5F7A87DDBD10D478C248 /* Pods-HealthKitReporter_Example-umbrella.h */, + C1DF9C7E917631DB50FD5DEDE8CDA43A /* Pods-HealthKitReporter_Example.debug.xcconfig */, + 10ED9239B0ED1C13D65048DF6C2EDD88 /* Pods-HealthKitReporter_Example.release.xcconfig */, ); - name = Service; - path = Sources/Service; + name = "Pods-HealthKitReporter_Example"; + path = "Target Support Files/Pods-HealthKitReporter_Example"; sourceTree = ""; }; - 042023AE26178860001C40F7 /* Retriever */ = { + 33DA41BE95035A5CB65413832A54A7F5 /* Pods-HealthKitReporter_Tests */ = { isa = PBXGroup; children = ( - 042023AF26178860001C40F7 /* SeriesSampleRetriever.swift */, - 042023B026178860001C40F7 /* ElectrocardiogramRetriever.swift */, + 19106C382C9023657C61D1BE14E407E2 /* Pods-HealthKitReporter_Tests.modulemap */, + 4B41AA02842340FAE870ED55A3E10581 /* Pods-HealthKitReporter_Tests-acknowledgements.markdown */, + 859C0FD784EA382944470E55EC51F72F /* Pods-HealthKitReporter_Tests-acknowledgements.plist */, + 775C0010DC236F50A09CDEE5E5B878F4 /* Pods-HealthKitReporter_Tests-dummy.m */, + 44193B23B1FADB45496E1AA11C5B3002 /* Pods-HealthKitReporter_Tests-Info.plist */, + 54E896CEBBB0F7AB51775AD8DB2A3240 /* Pods-HealthKitReporter_Tests-umbrella.h */, + D4755EC74B169D2FA28AC646D8EE2033 /* Pods-HealthKitReporter_Tests.debug.xcconfig */, + B4665EC9F0AB7C6F5920DFFC6369A299 /* Pods-HealthKitReporter_Tests.release.xcconfig */, ); - path = Retriever; + name = "Pods-HealthKitReporter_Tests"; + path = "Target Support Files/Pods-HealthKitReporter_Tests"; sourceTree = ""; }; - 042023B326178860001C40F7 /* Model */ = { + 3EC752C055E74E43448E3F9267DD1EF5 /* Payload */ = { isa = PBXGroup; children = ( - 042023B426178860001C40F7 /* Payload */, - 042023C726178860001C40F7 /* Original.swift */, - 042023C826178860001C40F7 /* UnitConvertable.swift */, - 042023C926178860001C40F7 /* Type */, - 042023D626178860001C40F7 /* Payload.swift */, - 042023D726178860001C40F7 /* UpdateFrequency.swift */, - 042023D826178860001C40F7 /* Harmonizable.swift */, - 042023D926178860001C40F7 /* PreferredUnit.swift */, + 7354B0BC2C62945F005297E1 /* ClinicalRecord.swift */, + FAF5FC29558E97773504BFB7A6E3F0B7 /* ActivitySummary.swift */, + 04FBB513B464D9F96552E98FAE1343BF /* Category.swift */, + B7389FA911D6AAD9522A038D7CAA3770 /* Characteristic.swift */, + 9DA4445FA0413B69A507EE04B90E310E /* Correlation.swift */, + 8B06AD19CEC288C0886F873C782AAD11 /* DeletedObject.swift */, + 3D69270819100EAB8BDBF1A42474EDED /* Device.swift */, + 021777A613B44D20DDCE3CA6CFED76E4 /* Electrocardiogram.swift */, + 49E4CCB9A739C5D6C44E6FDE3CBA336A /* HeartbeatSeries.swift */, + 14EAB9F96C66944F221F1658FD262635 /* Identifiable.swift */, + 4F465225C97C1D55104FE46F280F9740 /* Quantity.swift */, + 9FFDBE6EB771F9C6CA4167E336AF7A87 /* Sample.swift */, + 355655E0A1867FAA9D1FAFD4FABB7F4C /* Source.swift */, + 98AF73ECB6BABADE8B248920630A75CF /* SourceRevision.swift */, + 276C0E1C96007154F3EB63D85D341CCD /* Statistics.swift */, + 8671054852BAA6C7E7CC6C86B5002C7F /* VisionPrescription.swift */, + AC2D54E14A48876FEF4AB7FC0D65A027 /* Workout.swift */, + 3DA80F32525A8BDE69FA77E6CB72B5BE /* WorkoutConfiguration.swift */, + F84D25CD6B9F6BE671048EA498BCD092 /* WorkoutEvent.swift */, + 2E1E2342E262E1503D3E8EA5D9144B70 /* WorkoutRoute.swift */, ); - name = Model; - path = Sources/Model; + path = Payload; sourceTree = ""; }; - 042023B426178860001C40F7 /* Payload */ = { + 578452D2E740E91742655AC8F1636D1F /* iOS */ = { isa = PBXGroup; children = ( - 042023B626178860001C40F7 /* Source.swift */, - 042023B726178860001C40F7 /* Statistics.swift */, - 042023B826178860001C40F7 /* Workout.swift */, - 042023B926178860001C40F7 /* Correlation.swift */, - 042023BA26178860001C40F7 /* Sample.swift */, - 042023BB26178860001C40F7 /* Quantity.swift */, - 042023BC26178860001C40F7 /* WorkoutRoute.swift */, - 042023BD26178860001C40F7 /* DeletedObject.swift */, - 042023BE26178860001C40F7 /* Electrocardiogram.swift */, - 042023BF26178860001C40F7 /* WorkoutEvent.swift */, - 042023C026178860001C40F7 /* ActivitySummary.swift */, - 042023C126178860001C40F7 /* Category.swift */, - 042023C226178860001C40F7 /* Identifiable.swift */, - 042023C326178860001C40F7 /* Device.swift */, - 042023C426178860001C40F7 /* WorkoutConfiguration.swift */, - 042023C526178860001C40F7 /* Characteristic.swift */, - 042023C626178860001C40F7 /* SourceRevision.swift */, - 04F6E1752715D6B800A63807 /* HeartbeatSeries.swift */, + 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */, ); - path = Payload; + name = iOS; sourceTree = ""; }; - 042023C926178860001C40F7 /* Type */ = { + 843BE870623805F8E69DF06C55740F7B /* Sample */ = { isa = PBXGroup; children = ( - 042023CA26178860001C40F7 /* CharacteristicType.swift */, - 042023CB26178860001C40F7 /* ActivitySummaryType.swift */, - 042023CC26178860001C40F7 /* Sample */, - 042023D526178860001C40F7 /* ObjectType.swift */, + 7354B0B62C6293B4005297E1 /* ClinicalType.swift */, + D95556BAE1B44A602CBAA93EDD3BB464 /* CategoryType.swift */, + D17B2FDE0B6D0320BE2EB63FF8E7C28C /* CorrelationType.swift */, + DAAC829BB74B370CC624B2BF0FB92560 /* DocumentType.swift */, + 67FC5BA46B00F310A4C8F9DA5DA7B9E8 /* ElectrocardiogramType.swift */, + A6CCC81EA5C6B1365AA83E14BA201559 /* QuantityType.swift */, + C7114076D9A9EBCD319323158DACCB3B /* SampleType.swift */, + B39A807B10BADAA7683C62A54AE2F1DF /* SeriesType.swift */, + E2DCB207B3C0C062B28F5EE3DBFB4B7B /* VisionPrescriptionType.swift */, + 96183C6EFBB56F5D2AE474F39E897793 /* WorkoutType.swift */, ); - path = Type; + path = Sample; sourceTree = ""; }; - 042023CC26178860001C40F7 /* Sample */ = { + 99288F870A92ECAD92DAE0C7982CDF9A /* Model */ = { isa = PBXGroup; children = ( - 042023CD26178860001C40F7 /* QuantityType.swift */, - 042023CE26178860001C40F7 /* CategoryType.swift */, - 042023CF26178860001C40F7 /* SeriesType.swift */, - 042023D026178860001C40F7 /* ElectrocardiogramType.swift */, - 042023D126178860001C40F7 /* SampleType.swift */, - 042023D226178860001C40F7 /* DocumentType.swift */, - 042023D326178860001C40F7 /* WorkoutType.swift */, - 042023D426178860001C40F7 /* CorrelationType.swift */, + 7835AED3290DA39000D9CB35 /* Metadata.swift */, + 3DAC7CB4A7DBBBA1D3242C5A8790A749 /* Harmonizable.swift */, + 65F22F9819EE157ADFD08520D456C6A4 /* Original.swift */, + 1DEFD53A33731860ACED9D7FDC45A703 /* Payload.swift */, + 6B508D98C4C56C97BDB8D0D1BB46E38F /* PreferredUnit.swift */, + 222111EB6500A946E4CCADB957300A19 /* UnitConvertable.swift */, + 908029735F55FEA9CACDB0D1A7D54496 /* UpdateFrequency.swift */, + 3EC752C055E74E43448E3F9267DD1EF5 /* Payload */, + CBF2741B831E20EA0814D81820BBBF98 /* Type */, ); - path = Sample; + name = Model; + path = Sources/Model; sourceTree = ""; }; - 1B4D5707885DF5F6A16D9EB25EC9D18E /* Pods-HealthKitReporter_Example */ = { + B419BC628F9D5AFE64003B7731E4EEBC /* Targets Support Files */ = { isa = PBXGroup; children = ( - BA526D72C16C6C80D67D285E6CE11803 /* Pods-HealthKitReporter_Example.modulemap */, - C0EC02AC4B15CC5111FCF6837D0734DB /* Pods-HealthKitReporter_Example-acknowledgements.markdown */, - E58E764D298A13A6D23E438089A52F4D /* Pods-HealthKitReporter_Example-acknowledgements.plist */, - DBB4C8B104BDB5BB5ABE67400176B082 /* Pods-HealthKitReporter_Example-dummy.m */, - 9602EB29FFFC99DDBC1B33C58FBA8B04 /* Pods-HealthKitReporter_Example-frameworks.sh */, - 989097361B77629199333A71012885BA /* Pods-HealthKitReporter_Example-Info.plist */, - 2810499E4BCD5F7A87DDBD10D478C248 /* Pods-HealthKitReporter_Example-umbrella.h */, - C1DF9C7E917631DB50FD5DEDE8CDA43A /* Pods-HealthKitReporter_Example.debug.xcconfig */, - 10ED9239B0ED1C13D65048DF6C2EDD88 /* Pods-HealthKitReporter_Example.release.xcconfig */, + 1B4D5707885DF5F6A16D9EB25EC9D18E /* Pods-HealthKitReporter_Example */, + 33DA41BE95035A5CB65413832A54A7F5 /* Pods-HealthKitReporter_Tests */, ); - name = "Pods-HealthKitReporter_Example"; - path = "Target Support Files/Pods-HealthKitReporter_Example"; + name = "Targets Support Files"; sourceTree = ""; }; - 33DA41BE95035A5CB65413832A54A7F5 /* Pods-HealthKitReporter_Tests */ = { + CBF2741B831E20EA0814D81820BBBF98 /* Type */ = { isa = PBXGroup; children = ( - 19106C382C9023657C61D1BE14E407E2 /* Pods-HealthKitReporter_Tests.modulemap */, - 4B41AA02842340FAE870ED55A3E10581 /* Pods-HealthKitReporter_Tests-acknowledgements.markdown */, - 859C0FD784EA382944470E55EC51F72F /* Pods-HealthKitReporter_Tests-acknowledgements.plist */, - 775C0010DC236F50A09CDEE5E5B878F4 /* Pods-HealthKitReporter_Tests-dummy.m */, - 44193B23B1FADB45496E1AA11C5B3002 /* Pods-HealthKitReporter_Tests-Info.plist */, - 54E896CEBBB0F7AB51775AD8DB2A3240 /* Pods-HealthKitReporter_Tests-umbrella.h */, - D4755EC74B169D2FA28AC646D8EE2033 /* Pods-HealthKitReporter_Tests.debug.xcconfig */, - B4665EC9F0AB7C6F5920DFFC6369A299 /* Pods-HealthKitReporter_Tests.release.xcconfig */, + 44545002736B1F05EECB221CEBFAE961 /* ActivitySummaryType.swift */, + 87DB34BFBC9BF8162EBD02D5C6D298C3 /* CharacteristicType.swift */, + 4BD29D23F901C237B31A5D692F9D9713 /* ObjectType.swift */, + 843BE870623805F8E69DF06C55740F7B /* Sample */, ); - name = "Pods-HealthKitReporter_Tests"; - path = "Target Support Files/Pods-HealthKitReporter_Tests"; + path = Type; sourceTree = ""; }; - 658DE510FAFFF267F80CCDB3575F73F3 /* HealthKitReporter */ = { + CF1408CF629C7361332E53B88F7BD30C = { isa = PBXGroup; children = ( - 042023DB26178860001C40F7 /* HealthKitReporter.swift */, - 042023DA26178860001C40F7 /* HealthKitError.swift */, - 0420239026178860001C40F7 /* Decorator */, - 042023B326178860001C40F7 /* Model */, - 042023AB26178860001C40F7 /* Service */, - C97B85C185FC0E98C9FE5642D9176804 /* Pod */, - 8F7D7E23541E930B99A5A62AB334DF56 /* Support Files */, + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, + D20FBA36FF886D2EDDD20B3B8F7F1CCF /* Development Pods */, + D210D550F4EA176C3123ED886F8F87F5 /* Frameworks */, + DFCC019D7C177AD1D0E40D6EE53D2EBA /* Products */, + B419BC628F9D5AFE64003B7731E4EEBC /* Targets Support Files */, ); - name = HealthKitReporter; - path = ../..; sourceTree = ""; }; - 8F7D7E23541E930B99A5A62AB334DF56 /* Support Files */ = { + D092319D1ED8522122BAC9CBE6A5C206 /* Decorator */ = { isa = PBXGroup; children = ( - 3893D52BF738F0CD1893DBF22997BD58 /* HealthKitReporter.modulemap */, - 4F7AB517F06E1D1713499728AC55C83C /* HealthKitReporter-dummy.m */, - D0323F7CE3BC4360566D5381CF38EDED /* HealthKitReporter-Info.plist */, - BFA0D072B8047DA9E144F9E577A0E8C7 /* HealthKitReporter-prefix.pch */, - 1418EAB84877F65C010D2DD616A65D44 /* HealthKitReporter-umbrella.h */, - 620026A50D6F3042580BA62B0F2A5E24 /* HealthKitReporter.debug.xcconfig */, - 50AA0CA84AA46A85BDCFA91A07CA472E /* HealthKitReporter.release.xcconfig */, + 7354B0B82C629433005297E1 /* Extensions+HKClinicalRecord.swift */, + 725EEB8C2CE54A8A15BDD5F3DB916AB3 /* Extensions+Date.swift */, + 84F2596E09A7D67E6EDBD73E42B8FFCA /* Extensions+DateComponents.swift */, + C36CEC51B9FF98870F6847C451B710FA /* Extensions+Dictionary.swift */, + 88988A956142E177BE9C9C195EE79691 /* Extensions+Double.swift */, + AA110780BB027D6B81BD60D0C560AFFA /* Extensions+Encodable.swift */, + 48F38C03BC9C922F42622F968658E132 /* Extensions+HKActivityMoveMode.swift */, + C3C5CC536BD777F389D6C6B4F9C1CAFF /* Extensions+HKActivitySummary.swift */, + B0C5308EDBE4A3479D38CB48FCA95B94 /* Extensions+HKBiologicalSex.swift */, + 3102A396ED211624C89742DC1A2DB605 /* Extensions+HKBloodType.swift */, + F5D11E89F4AA8A564655156AD5D4F8F2 /* Extensions+HKCategorySample.swift */, + 2D09718B54ED3E490683579AA4C5D5F9 /* Extensions+HKCategoryType.swift */, + 6B8A9E7706067AF7560F39C291BEE3AC /* Extensions+HKCategoryValue.swift */, + 8155DF4384A333207865B8FB24B9D8AA /* Extensions+HKCategoryValueAppetiteChanges.swift */, + B00A32093EC52BD97BC9CD2DE792DBD4 /* Extensions+HKCategoryValueAppleStandHour.swift */, + 779D0EE7F0734A26C238E0380C189EC2 /* Extensions+HKCategoryValueAppleWalkingSteadinessEvent.swift */, + E7A8940EF42B5DB48394C8EEC564DDD2 /* Extensions+HKCategoryValueAudioExposureEvent.swift */, + AA77ED0476C73CBFC08F47BF12D6D1E9 /* Extensions+HKCategoryValueCervicalMucusQuality.swift */, + E126ADB64FCC998644BE8A1F2EA58259 /* Extensions+HKCategoryValueContraceptive.swift */, + 106F1D0F830265A82D691E1B3C0C316C /* Extensions+HKCategoryValueEnvironmentalAudioExposureEvent.swift */, + D2F7E69DFF38A7DCAD305271E21E7B66 /* Extensions+HKCategoryValueHeadphoneAudioExposureEvent.swift */, + 850D6A69E2DC43940596668A9534251E /* Extensions+HKCategoryValueLowCardioFitnessEvent.swift */, + 9F8156E71A7309B2C760AEE3BCB535F4 /* Extensions+HKCategoryValueMenstrualFlow.swift */, + ACD4232F0A2B118D033985000AD5D0CB /* Extensions+HKCategoryValueOvulationTestResult.swift */, + 5E4CB548A95CBF4A96C788AF488B22EA /* Extensions+HKCategoryValuePregnancyTestResult.swift */, + 3CA4849040BD152BBA56AB34E8712EDB /* Extensions+HKCategoryValuePresence.swift */, + 5FCDDDC9653ECC45320F6CFA3DAF8A4A /* Extensions+HKCategoryValueProgesteroneTestResult.swift */, + EECFB79FD2730DB471F3DB655747E03B /* Extensions+HKCategoryValueSeverity.swift */, + 6F13D5F3D30DFF2CB1E1967820E6546A /* Extensions+HKCategoryValueSleepAnalysis.swift */, + 884CF18D0A5BA4159D6BD793F9F1BC6F /* Extensions+HKCorrelation.swift */, + 6DF381181DC7BCFFB41F309825BF2D06 /* Extensions+HKElectrocardiogram.swift */, + 285279B6B26D290EA701D3EC4966C088 /* Extensions+HKFitzpatrickSkinType.swift */, + 82063CBFA5BA4A9FFAD96EC80564B6EF /* Extensions+HKHeartbeatSeriesSample.swift */, + 67E73DDC6B7FB70C6BC6A76DD7AD0C93 /* Extensions+HKQuantitiySample.swift */, + 8D97E81B98A909D030B0362B21F0DD50 /* Extensions+HKQuantityType.swift */, + 9AB9C2D8B500080A5420C0810894C5E4 /* Extensions+HKSample.swift */, + FBC7718A4D411B5E691FCAAE7FD47FEF /* Extensions+HKSourceRevision.swift */, + A393395C8707BD18CA7E2D5CF3FE4822 /* Extensions+HKStatistics.swift */, + EED4C86C81FD5948A1AD11F9C4446C54 /* Extensions+HKVisionPrescription.swift */, + 7C35147CFB0794752DC14C3CAC878E0F /* Extensions+HKVisionPrescriptionType.swift */, + 822BE42AD8A5F44EFA02C8B679535B70 /* Extensions+HKWheelchairUse.swift */, + 9C160DDC8F72F8216539DE0DC7E0C1A6 /* Extensions+HKWorkout.swift */, + D0C024B54024A1874B482C78F65CC70A /* Extensions+HKWorkoutActivityType.swift */, + C1F2F3C0D5878CC84A0A2608512482CB /* Extensions+HKWorkoutConfiguration.swift */, + 2977D7A51AC617CDFE96F27412486B8D /* Extensions+HKWorkoutEvent.swift */, + 8BD8270979E130D9007CC7FFA74E2407 /* Extensions+HKWorkoutEventType.swift */, + DD811C573A49E507F0A87C150AE3AF32 /* Extensions+HKWorkoutRoute.swift */, + 6AA24F0D87CCAC22B1512D722F8B81C1 /* Extensions+NSPredicate.swift */, + 3AEA8093D9225C79AA3F1A0C3DB4AC54 /* Extensions+String.swift */, ); - name = "Support Files"; - path = "Example/Pods/Target Support Files/HealthKitReporter"; + name = Decorator; + path = Sources/Decorator; sourceTree = ""; }; - B419BC628F9D5AFE64003B7731E4EEBC /* Targets Support Files */ = { + D20FBA36FF886D2EDDD20B3B8F7F1CCF /* Development Pods */ = { isa = PBXGroup; children = ( - 1B4D5707885DF5F6A16D9EB25EC9D18E /* Pods-HealthKitReporter_Example */, - 33DA41BE95035A5CB65413832A54A7F5 /* Pods-HealthKitReporter_Tests */, + 14DA66AAA298CA130F83EDADA52B6D5E /* HealthKitReporter */, ); - name = "Targets Support Files"; + name = "Development Pods"; sourceTree = ""; }; - B592543538995693FE3F3E9EEBDA5158 /* Products */ = { + D210D550F4EA176C3123ED886F8F87F5 /* Frameworks */ = { isa = PBXGroup; children = ( - 414D7DD0DA5581301732C4FA52D8A2E7 /* HealthKitReporter.framework */, - 0CBCDB9707C28427FF60B97538188EDE /* Pods_HealthKitReporter_Example.framework */, - 71D8BEAF4ADFF6BB7D99C7D261B03A10 /* Pods_HealthKitReporter_Tests.framework */, + 578452D2E740E91742655AC8F1636D1F /* iOS */, ); - name = Products; + name = Frameworks; sourceTree = ""; }; - C0834CEBB1379A84116EF29F93051C60 /* iOS */ = { + D45F7EE8C6A658ADD6347D7BE56FA147 /* Retriever */ = { isa = PBXGroup; children = ( - 3212113385A8FBBDB272BD23C409FF61 /* Foundation.framework */, + B90113B9E28C8E17E86F0B0F1FBF6898 /* ElectrocardiogramRetriever.swift */, + E0C1816183E171B9EB7ACB57947D6715 /* SeriesSampleRetriever.swift */, ); - name = iOS; + path = Retriever; sourceTree = ""; }; - C97B85C185FC0E98C9FE5642D9176804 /* Pod */ = { + D55E7EFACDC02B74FAE6B9F24FE9C4B0 /* Pod */ = { isa = PBXGroup; children = ( - E66BFAA856AE9B9B4C90D91FC25EDC39 /* HealthKitReporter.podspec */, - 3437F34D44A783E1EFFA682E39474B09 /* LICENSE */, - 1716C45425278E190037EA4E /* CHANGELOG.md */, - 27617830750DC147AFDBE7EA9D445C3A /* README.md */, + 88FBE9056A11F9DCE6CAEA1B354BAF9F /* HealthKitReporter.podspec */, + 38CA3DC113C54083F304FF7EEF4E9068 /* LICENSE */, + 9614D2031F58F5E6672FA11E73049B17 /* README.md */, ); name = Pod; sourceTree = ""; }; - CF1408CF629C7361332E53B88F7BD30C = { + D585A22F16355D1647D19C8483AF6A81 /* Tests */ = { isa = PBXGroup; children = ( - 17CD92EF255C095B00F3CD09 /* build_script.sh */, - 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, - FDD3E017DDCCD598F6098E7C7C4827AE /* Development Pods */, - D210D550F4EA176C3123ED886F8F87F5 /* Frameworks */, - B592543538995693FE3F3E9EEBDA5158 /* Products */, - B419BC628F9D5AFE64003B7731E4EEBC /* Targets Support Files */, + 5E295CBB228A75CA020C76C2067BF4C7 /* ActivitySummaryTests.swift */, + D23E54060150E4FF1128E7B1BE26ED26 /* CategoryTests.swift */, + 198D71D3AF21150E7A31E171D9847E1E /* CharacteristicTests.swift */, + C51C0F692BD912CE07C795C872381A68 /* CorrelationTests.swift */, + 101CB243B88135DF695DCD79346E7AEF /* DeletedObjectTests.swift */, + 7F9C1D2DC980211C3F4641DE18E0D0F7 /* DeviceTests.swift */, + CA30DC80B6382A498E796CBFBC0355E5 /* ElectrocardiogramTests.swift */, + 1B5A44750CB1C28DBB79D5FB395FCF59 /* HealthKitReporterTests.swift */, + CCD513890913592D2CC8AEAA4A52A42D /* HeartbeatSeriesTests.swift */, + B1B657204828C2E3722C952AD326C255 /* QuantityTests.swift */, + B983E73004D5D8DDF1A18C149EA2EED5 /* SourceRevisionTests.swift */, + BBBD3A4D4F856461FEDF0C9BD870F1D0 /* SourceTests.swift */, + 7614D1074DB0BD9144DC75E02B319E09 /* StatisticsTests.swift */, + F24DB46EFB8B2ADE86C9B96CA26545B5 /* WorkoutConfigurationTests.swift */, + C47FE1F97CBF34F88CF449047E61FEB2 /* WorkoutEventTests.swift */, + E32F57F22FDB65E7823F8D10B88C959A /* WorkoutRouteTests.swift */, + B8BFD5719C667AF1C203A2A09A771312 /* WorkoutTests.swift */, ); + name = Tests; sourceTree = ""; }; - D210D550F4EA176C3123ED886F8F87F5 /* Frameworks */ = { + D92E6A4864959C0B5145E94C3F8D8AC1 /* Service */ = { isa = PBXGroup; children = ( - C0834CEBB1379A84116EF29F93051C60 /* iOS */, + BFBFF2DDED0808E73F55AA6D99367596 /* HealthKitManager.swift */, + BF9C8313AFF8190CEDAE726029E26604 /* HealthKitObserver.swift */, + C8C7734C464098185A3DC8F3A784D58D /* HealthKitReader.swift */, + 843D457EC25CABF71EBFA5B80912C088 /* HealthKitWriter.swift */, + D45F7EE8C6A658ADD6347D7BE56FA147 /* Retriever */, ); - name = Frameworks; + name = Service; + path = Sources/Service; sourceTree = ""; }; - FDD3E017DDCCD598F6098E7C7C4827AE /* Development Pods */ = { + D94EAC2CB68BFA623930C1B634294D1E /* Support Files */ = { isa = PBXGroup; children = ( - 658DE510FAFFF267F80CCDB3575F73F3 /* HealthKitReporter */, + DEAD47E57F8ECF25A1220E65DFAB46B3 /* HealthKitReporter.modulemap */, + 921DD3F31C4FBB5AE97A65943317407E /* HealthKitReporter-dummy.m */, + 83D631E02E31514291F7514D4E6A382A /* HealthKitReporter-Info.plist */, + F47BE8DAC9541A04DE27C3D911D7B6F7 /* HealthKitReporter-prefix.pch */, + 9B080F197C40B7ACE4394268D1CDBC6A /* HealthKitReporter-umbrella.h */, + 9DDE7FCD8E64573651E4D6FA92385669 /* HealthKitReporter-Unit-Tests-frameworks.sh */, + 49D05D7B03F3832E1AEB9C0DE45A27CA /* HealthKitReporter-Unit-Tests-Info.plist */, + AA742DEAB1A5A59D4E6C6865DAA33748 /* HealthKitReporter-Unit-Tests-prefix.pch */, + FA34A422D5D91CA343375D9F5656E0C9 /* HealthKitReporter.debug.xcconfig */, + 39C648D3DC1753ED463E13801E3D76AD /* HealthKitReporter.release.xcconfig */, + 09A91F461B623281D4F426E925D6B6BE /* HealthKitReporter.unit-tests.debug.xcconfig */, + 1DA81DC75879F428CC7DD41B6ABAE326 /* HealthKitReporter.unit-tests.release.xcconfig */, ); - name = "Development Pods"; + name = "Support Files"; + path = "Example/Pods/Target Support Files/HealthKitReporter"; + sourceTree = ""; + }; + DFCC019D7C177AD1D0E40D6EE53D2EBA /* Products */ = { + isa = PBXGroup; + children = ( + 414D7DD0DA5581301732C4FA52D8A2E7 /* HealthKitReporter */, + BA8B062B4C30F0E7B9F7122282C803A1 /* HealthKitReporter-Unit-Tests */, + 0CBCDB9707C28427FF60B97538188EDE /* Pods-HealthKitReporter_Example */, + 71D8BEAF4ADFF6BB7D99C7D261B03A10 /* Pods-HealthKitReporter_Tests */, + ); + name = Products; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 08B4D81E977067CD2290F68732ACAC4B /* Headers */ = { + 182D3017A21976276DF321A4876B8E7C /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - B102DF75C35963420AB33D8269899D81 /* HealthKitReporter-umbrella.h in Headers */, + C0F1A63843EE02234A1A9B1227D0E13D /* HealthKitReporter-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - 1B697BD97B362773ED6FA1C2BF862BBA /* Headers */ = { + 2800468C7731A4571D777F5256F0F205 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 4A2928A4F62607E28C214719CE56A176 /* Pods-HealthKitReporter_Example-umbrella.h in Headers */, + 355B81ED05D9A2E1226E02948D9CEE65 /* Pods-HealthKitReporter_Tests-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - F1B7D85C600648526ED46A26BC51D03F /* Headers */ = { + 9E893E23A82FF702EA2AF7510237974E /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 1BB37D34E5F48888A5C051AD9AE21C9D /* Pods-HealthKitReporter_Tests-umbrella.h in Headers */, + FF065D19CB956B095A4377990E2715CB /* Pods-HealthKitReporter_Example-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -571,50 +682,49 @@ /* Begin PBXNativeTarget section */ 1C83EA59492248E951F52C6A762B305F /* Pods-HealthKitReporter_Tests */ = { isa = PBXNativeTarget; - buildConfigurationList = 909FC5628D7365862B57B291F08245AA /* Build configuration list for PBXNativeTarget "Pods-HealthKitReporter_Tests" */; + buildConfigurationList = 29C84D345321537916857512219F2695 /* Build configuration list for PBXNativeTarget "Pods-HealthKitReporter_Tests" */; buildPhases = ( - F1B7D85C600648526ED46A26BC51D03F /* Headers */, - 07D53EEA9B8D803C4C3D0F4B23EA9C92 /* Sources */, - 4D04B966B9E84405230AFE63FF6C8124 /* Frameworks */, - 0ED5EDE42CCF6C3CFA7C54B77F483784 /* Resources */, + 2800468C7731A4571D777F5256F0F205 /* Headers */, + B37C5DA4B754C3558955C6D07429B74F /* Sources */, + 336CC995EA629F3CE34C679CC728F944 /* Frameworks */, + 5FA0210B9B220936D1003C22A9EB4004 /* Resources */, ); buildRules = ( ); dependencies = ( - 7FBAEE0B17571BB78AA23BAC547A7B9F /* PBXTargetDependency */, ); name = "Pods-HealthKitReporter_Tests"; - productName = "Pods-HealthKitReporter_Tests"; - productReference = 71D8BEAF4ADFF6BB7D99C7D261B03A10 /* Pods_HealthKitReporter_Tests.framework */; + productName = Pods_HealthKitReporter_Tests; + productReference = 71D8BEAF4ADFF6BB7D99C7D261B03A10 /* Pods-HealthKitReporter_Tests */; productType = "com.apple.product-type.framework"; }; 28111CA3729B131600777B0AE0E0AF79 /* Pods-HealthKitReporter_Example */ = { isa = PBXNativeTarget; - buildConfigurationList = 462C3705D1ECE509B74B839B20B64CFC /* Build configuration list for PBXNativeTarget "Pods-HealthKitReporter_Example" */; + buildConfigurationList = B203D0872371CAF5CA06C23E4B167704 /* Build configuration list for PBXNativeTarget "Pods-HealthKitReporter_Example" */; buildPhases = ( - 1B697BD97B362773ED6FA1C2BF862BBA /* Headers */, - 034B32F82D6815889CBED8B6005D661A /* Sources */, - 696BAA608A18B81E1A6BA5A183C9B0AE /* Frameworks */, - 72D8C4DC2AEDFD293AA02F3D8EFA82DE /* Resources */, + 9E893E23A82FF702EA2AF7510237974E /* Headers */, + B4800AF4BCB62F4DDA196B3430390D40 /* Sources */, + 80BA64646C59D79FFB9E5A948E6FF63E /* Frameworks */, + 72EB5DD50678E4E1602B92E915D01044 /* Resources */, ); buildRules = ( ); dependencies = ( - 3B81A1703A3290BFD8875EA5F35FF447 /* PBXTargetDependency */, + 8A109F2D27CACCF9DD624F87B2CE634B /* PBXTargetDependency */, ); name = "Pods-HealthKitReporter_Example"; - productName = "Pods-HealthKitReporter_Example"; - productReference = 0CBCDB9707C28427FF60B97538188EDE /* Pods_HealthKitReporter_Example.framework */; + productName = Pods_HealthKitReporter_Example; + productReference = 0CBCDB9707C28427FF60B97538188EDE /* Pods-HealthKitReporter_Example */; productType = "com.apple.product-type.framework"; }; 5A02BB0F1AC44F7E176E662038412466 /* HealthKitReporter */ = { isa = PBXNativeTarget; - buildConfigurationList = 12BC7DE726408235B7E6481391999AE1 /* Build configuration list for PBXNativeTarget "HealthKitReporter" */; + buildConfigurationList = 2BF9C5E43072C436F6AF1BAD30FD34E6 /* Build configuration list for PBXNativeTarget "HealthKitReporter" */; buildPhases = ( - 08B4D81E977067CD2290F68732ACAC4B /* Headers */, - 062134CF10046F84DF2D468A7D805B15 /* Sources */, - 33EEEC7E47F8E6522CCF9B17C6BFA274 /* Frameworks */, - 1D20CAF7A838558D64D08503D1DF8366 /* Resources */, + 182D3017A21976276DF321A4876B8E7C /* Headers */, + 01EF968F9BF46CD88DC11B4F32BCA63E /* Sources */, + 11D0F81C30BB0297F53AD8C3FE961499 /* Frameworks */, + 16C3806C0FB18274614E444CEA044C5A /* Resources */, ); buildRules = ( ); @@ -622,38 +732,52 @@ ); name = HealthKitReporter; productName = HealthKitReporter; - productReference = 414D7DD0DA5581301732C4FA52D8A2E7 /* HealthKitReporter.framework */; + productReference = 414D7DD0DA5581301732C4FA52D8A2E7 /* HealthKitReporter */; productType = "com.apple.product-type.framework"; }; + D2EAD3408A5BC5988D5610DA6C4778C6 /* HealthKitReporter-Unit-Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = BF6E6487B3C43FA0FAA05D5B638ED4BB /* Build configuration list for PBXNativeTarget "HealthKitReporter-Unit-Tests" */; + buildPhases = ( + B9FDBFBE87365143F02801B094F7777F /* Sources */, + 5F82A00BC1398E73D9C07FDE67F87B2A /* Frameworks */, + ED366048A40B79FB884228ED76BDB8FC /* Resources */, + DF5AB9A90B36B7218DFA941FC3FF5A29 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + EB3966D0FC1AB9EDFC564AADC3E16444 /* PBXTargetDependency */, + ); + name = "HealthKitReporter-Unit-Tests"; + productName = "HealthKitReporter-Unit-Tests"; + productReference = BA8B062B4C30F0E7B9F7122282C803A1 /* HealthKitReporter-Unit-Tests */; + productType = "com.apple.product-type.bundle.unit-test"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ BFDFE7DC352907FC980B868725387E98 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1100; - LastUpgradeCheck = 1220; - TargetAttributes = { - 5A02BB0F1AC44F7E176E662038412466 = { - LastSwiftMigration = 1240; - ProvisioningStyle = Automatic; - }; - }; + LastSwiftUpdateCheck = 1240; + LastUpgradeCheck = 1240; }; buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( - en, Base, + en, ); mainGroup = CF1408CF629C7361332E53B88F7BD30C; - productRefGroup = B592543538995693FE3F3E9EEBDA5158 /* Products */; + productRefGroup = DFCC019D7C177AD1D0E40D6EE53D2EBA /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 5A02BB0F1AC44F7E176E662038412466 /* HealthKitReporter */, + D2EAD3408A5BC5988D5610DA6C4778C6 /* HealthKitReporter-Unit-Tests */, 28111CA3729B131600777B0AE0E0AF79 /* Pods-HealthKitReporter_Example */, 1C83EA59492248E951F52C6A762B305F /* Pods-HealthKitReporter_Tests */, ); @@ -661,22 +785,28 @@ /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 0ED5EDE42CCF6C3CFA7C54B77F483784 /* Resources */ = { + 16C3806C0FB18274614E444CEA044C5A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5FA0210B9B220936D1003C22A9EB4004 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 1D20CAF7A838558D64D08503D1DF8366 /* Resources */ = { + 72EB5DD50678E4E1602B92E915D01044 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 1716C45525278E190037EA4E /* CHANGELOG.md in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 72D8C4DC2AEDFD293AA02F3D8EFA82DE /* Resources */ = { + ED366048A40B79FB884228ED76BDB8FC /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -685,177 +815,196 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + DF5AB9A90B36B7218DFA941FC3FF5A29 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/HealthKitReporter/HealthKitReporter-Unit-Tests-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/HealthKitReporter/HealthKitReporter.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/HealthKitReporter.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/HealthKitReporter/HealthKitReporter-Unit-Tests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ - 034B32F82D6815889CBED8B6005D661A /* Sources */ = { + 01EF968F9BF46CD88DC11B4F32BCA63E /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 6D095DA112AF90AB75DFD4484A214215 /* Pods-HealthKitReporter_Example-dummy.m in Sources */, + 551021AFC56F20ACE3F9B75BF91D178A /* ActivitySummary.swift in Sources */, + 0A73D80BDF12B704A492BCDC31B6DCE9 /* ActivitySummaryType.swift in Sources */, + 147CDFDAB74067118EACE3D27B3ABFB4 /* Category.swift in Sources */, + 2E85B9A398B2D95224290927BADC59E8 /* CategoryType.swift in Sources */, + 7354B0BD2C62945F005297E1 /* ClinicalRecord.swift in Sources */, + B9107578033FD63377AE5FE34612C96C /* Characteristic.swift in Sources */, + 920D2C33BD40F2FD60637DB22FC1D9E3 /* CharacteristicType.swift in Sources */, + 200F17D0556D0C72A0A94242E1A07846 /* Correlation.swift in Sources */, + 79023528495E32B002B9378AF8B238C4 /* CorrelationType.swift in Sources */, + F745CE840F5AD69627586294E70BB9F7 /* DeletedObject.swift in Sources */, + 72E09764C778579D86111A27DC1C24B3 /* Device.swift in Sources */, + 9844D3E4EDD2E806F0916B04CC5086A4 /* DocumentType.swift in Sources */, + CAB57E3D3059CB3AF0C1B7392F1FBD54 /* Electrocardiogram.swift in Sources */, + 7835AED4290DA39000D9CB35 /* Metadata.swift in Sources */, + 8A89D3FA0C3C9932CA9E03FB654AEA8E /* ElectrocardiogramRetriever.swift in Sources */, + E859234CF9FACD084BBE36CB32BDC498 /* ElectrocardiogramType.swift in Sources */, + 435C48B0BABA6E0D626BDFF35197E09F /* Extensions+Date.swift in Sources */, + 69AC1E9AD1B251C9334137C6A7A7EA50 /* Extensions+DateComponents.swift in Sources */, + 3B069AEBF4625FADFA37445B90216EB4 /* Extensions+Dictionary.swift in Sources */, + 79534F864D7D0B2D2C1B99B849FF1B6F /* Extensions+Double.swift in Sources */, + 5EA48A6869F09486249508AE2AF8448C /* Extensions+Encodable.swift in Sources */, + 34B24C3BBF39229859235BB61B180F66 /* Extensions+HKActivityMoveMode.swift in Sources */, + F283F24518E80B425D8D77E52C42B198 /* Extensions+HKActivitySummary.swift in Sources */, + 085C4A223BCECF792391B96C5D0A2B36 /* Extensions+HKBiologicalSex.swift in Sources */, + EC10C7A265255331473CED36F50D3AC3 /* Extensions+HKBloodType.swift in Sources */, + DA80BDB1E10491AB598D57077ADDA392 /* Extensions+HKCategorySample.swift in Sources */, + E9C407EDAF4A8F76F1639238845151B0 /* Extensions+HKCategoryType.swift in Sources */, + 426068AD7D31C9A261291B9054F05069 /* Extensions+HKCategoryValue.swift in Sources */, + 2E4E9C39BC2318A88A21075F3ABE1C59 /* Extensions+HKCategoryValueAppetiteChanges.swift in Sources */, + 140AA65C0D16953B85C007B0D4CCF425 /* Extensions+HKCategoryValueAppleStandHour.swift in Sources */, + 0C9C586C9E9F144B0B17E4C6C226703A /* Extensions+HKCategoryValueAppleWalkingSteadinessEvent.swift in Sources */, + 6C771B0934C9169274D7DC1BEE06D6DD /* Extensions+HKCategoryValueAudioExposureEvent.swift in Sources */, + 7777396AD7F76C1FFA915EDB8D68FDD7 /* Extensions+HKCategoryValueCervicalMucusQuality.swift in Sources */, + E86D00B074C381527053C300F8793A7A /* Extensions+HKCategoryValueContraceptive.swift in Sources */, + 47B04648FE7574C61BDE353E4A0FBEE3 /* Extensions+HKCategoryValueEnvironmentalAudioExposureEvent.swift in Sources */, + 70ED962EB2E153C9FF71449F183EB92C /* Extensions+HKCategoryValueHeadphoneAudioExposureEvent.swift in Sources */, + 3910D69C192F2559F8374D3574ABCF30 /* Extensions+HKCategoryValueLowCardioFitnessEvent.swift in Sources */, + 659F9E39C928EEB8A3977418B5A7B593 /* Extensions+HKCategoryValueMenstrualFlow.swift in Sources */, + 73548876675C72560DA62B3A054517EE /* Extensions+HKCategoryValueOvulationTestResult.swift in Sources */, + B2E7ACF4D53BF3810256B44734A833C0 /* Extensions+HKCategoryValuePregnancyTestResult.swift in Sources */, + 8F66F2270182E25A44CFA3466CF4738E /* Extensions+HKCategoryValuePresence.swift in Sources */, + 0E46AC8F19F9BB4BBC265A7226DB3B55 /* Extensions+HKCategoryValueProgesteroneTestResult.swift in Sources */, + 85C1539D37A1A4DC1455AD6D0F673392 /* Extensions+HKCategoryValueSeverity.swift in Sources */, + E05ED46D0B9E502A8509548863F37426 /* Extensions+HKCategoryValueSleepAnalysis.swift in Sources */, + CB6D1D26CE4CF803639A44758E483AC5 /* Extensions+HKCorrelation.swift in Sources */, + C96C836B7EDD50A806864069882D7FE7 /* Extensions+HKElectrocardiogram.swift in Sources */, + 20AF3499ADBCC7E9DF3741473AA025B1 /* Extensions+HKFitzpatrickSkinType.swift in Sources */, + 631A8CE1D955DF01FBDA22E262D43F08 /* Extensions+HKHeartbeatSeriesSample.swift in Sources */, + 58DFA3501CE62007A9EA1ECF206E78E2 /* Extensions+HKQuantitiySample.swift in Sources */, + A6113A07AD3E2D34E5E1AE7043980190 /* Extensions+HKQuantityType.swift in Sources */, + 80927CB9E7B68F1848A6CB18316621B6 /* Extensions+HKSample.swift in Sources */, + 45029B327ABC591B82420F5B5ACA1546 /* Extensions+HKSourceRevision.swift in Sources */, + D42731D55DA0938AAE7AD1201ED4A891 /* Extensions+HKStatistics.swift in Sources */, + 3B8B32DDDBA4B54B80A4F19CE772D9EF /* Extensions+HKVisionPrescription.swift in Sources */, + 029D4E0D6599E806E448BEE08DE1F403 /* Extensions+HKVisionPrescriptionType.swift in Sources */, + CEEB5EDA0C1FDDA54FD5DC4DFCA9102E /* Extensions+HKWheelchairUse.swift in Sources */, + 586F99E0C15F52DFC70987226CBCF468 /* Extensions+HKWorkout.swift in Sources */, + D0C064564F2D8F4B765CF2261D0E9C7F /* Extensions+HKWorkoutActivityType.swift in Sources */, + 5848D7EE868C3B1FCD2CCFE5358BF672 /* Extensions+HKWorkoutConfiguration.swift in Sources */, + 7CB2390575AE1EC43C925441DAD19CC0 /* Extensions+HKWorkoutEvent.swift in Sources */, + B97B3E2DC4719994E52D45BDE54F2B36 /* Extensions+HKWorkoutEventType.swift in Sources */, + 88CB596B65F716E000A9F6EC19080786 /* Extensions+HKWorkoutRoute.swift in Sources */, + 9372FFED87F4BCFC2F558F84E6BCFC06 /* Extensions+NSPredicate.swift in Sources */, + 5FA118CFDE8A47F3FB23AD777CF90EF6 /* Extensions+String.swift in Sources */, + DD357B36A9B8D96E8DA7136FEC225D37 /* Harmonizable.swift in Sources */, + 1C5DBEBBC2505BEF589A15C25B28CC17 /* HealthKitError.swift in Sources */, + F8216DB950418CF83DB9C687F0C1807D /* HealthKitManager.swift in Sources */, + 16F0B23245CA12323EABAA69C2974442 /* HealthKitObserver.swift in Sources */, + F116D8C6B1F2E58DCA4C16A9A83F034C /* HealthKitReader.swift in Sources */, + D4AE1A99C05B6C20139AA1F1F2C5E318 /* HealthKitReporter.swift in Sources */, + 2157ACD70581E329A9B409B82ABF00EE /* HealthKitReporter-dummy.m in Sources */, + C5CB95D0A0CB1FDE0F28DD6BB711F789 /* HealthKitWriter.swift in Sources */, + D97F6240A09B04FC3B26FCD8E636B7B8 /* HeartbeatSeries.swift in Sources */, + 915883B325960F95B820446F38D722F1 /* Identifiable.swift in Sources */, + 2AA34BF15C2F9E49811A034CD7C86F54 /* ObjectType.swift in Sources */, + 9043883185F24CCAF73B1DFADE74B2BC /* Original.swift in Sources */, + A4DA272CF9C16C647EE397E650C8965E /* Payload.swift in Sources */, + 4167C4372313D714316FAF687151846C /* PreferredUnit.swift in Sources */, + 15632A43212028B6971FEEF3F4F60EAB /* Quantity.swift in Sources */, + 7354B0B72C6293B4005297E1 /* ClinicalType.swift in Sources */, + 40B4F5AA8240A68BEA9CB07284D179B9 /* QuantityType.swift in Sources */, + 46A4D70A3EF5E6455C6447E5C66293C1 /* Sample.swift in Sources */, + 6CEFD04B650EB3390000DF40063C18C2 /* SampleType.swift in Sources */, + D6635A98D8EDE329E6F3E52F6617BA47 /* SeriesSampleRetriever.swift in Sources */, + 7354B0BA2C629433005297E1 /* Extensions+HKClinicalRecord.swift in Sources */, + 194DCD765C577F4E4B0F785E3794B782 /* SeriesType.swift in Sources */, + A7B932E5511DCCF597CDF9EA44742AF2 /* Source.swift in Sources */, + C3F370BD24A59AC1833D0ABF52E319FB /* SourceRevision.swift in Sources */, + F60CA6F500FE6715F82D126B0209BB4E /* Statistics.swift in Sources */, + F0AF237BAD0314FA61FC6C54DE9C6F02 /* UnitConvertable.swift in Sources */, + 982BD189F9D48B4F1C84726AF8B523EE /* UpdateFrequency.swift in Sources */, + ECB5C12623BFF04405379E36BC404A08 /* VisionPrescription.swift in Sources */, + E9A782EE213CC4A9485DF504563E1047 /* VisionPrescriptionType.swift in Sources */, + 079AFADF352E0985438CC498831B9544 /* Workout.swift in Sources */, + 643CB7077DEEFC95C368A001BFF018CC /* WorkoutConfiguration.swift in Sources */, + C1BFD24F9EC16C7FEDB673AB4630A860 /* WorkoutEvent.swift in Sources */, + D7EAD3F389E691377CD303810BAEFFF3 /* WorkoutRoute.swift in Sources */, + EAF3612C219AE905B0F96C538C9E1BD1 /* WorkoutType.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 062134CF10046F84DF2D468A7D805B15 /* Sources */ = { + B37C5DA4B754C3558955C6D07429B74F /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 040EFF1126E4CA3600D37F04 /* Extensions+HKCategoryValueCervicalMucusQuality.swift in Sources */, - 042023F626178860001C40F7 /* HealthKitObserver.swift in Sources */, - 042023FA26178860001C40F7 /* HealthKitReader.swift in Sources */, - 0420240C26178860001C40F7 /* Characteristic.swift in Sources */, - 0420241626178860001C40F7 /* SampleType.swift in Sources */, - 0420241526178860001C40F7 /* ElectrocardiogramType.swift in Sources */, - 0420240726178860001C40F7 /* ActivitySummary.swift in Sources */, - 042023EB26178860001C40F7 /* Extensions+Encodable.swift in Sources */, - 0420240F26178860001C40F7 /* UnitConvertable.swift in Sources */, - 042023FD26178860001C40F7 /* Source.swift in Sources */, - 040EFF1D26E4CC1500D37F04 /* Extensions+HKCategoryValueHeadphoneAudioExposureEvent.swift in Sources */, - 042023F026178860001C40F7 /* Extensions+Date.swift in Sources */, - 040EFF1F26E4CCCC00D37F04 /* Extensions+HKCategoryValueEnvironmentalAudioExposureEvent.swift in Sources */, - 7351128AFE6D2C348D5CC138E73673A2 /* HealthKitReporter-dummy.m in Sources */, - 0420240026178860001C40F7 /* Correlation.swift in Sources */, - 042023F526178860001C40F7 /* Extensions+HKActivityMoveMode.swift in Sources */, - 040EFF1326E4CA6000D37F04 /* Extensions+HKCategoryValueAppleStandHour.swift in Sources */, - 040EFF0726E4C86C00D37F04 /* Extensions+HKCategoryValueAudioExposureEvent.swift in Sources */, - 0420241826178860001C40F7 /* WorkoutType.swift in Sources */, - 040EFF0D26E4C9A900D37F04 /* Extensions+HKCategoryValueMenstrualFlow.swift in Sources */, - 0420240226178860001C40F7 /* Quantity.swift in Sources */, - 042023F726178860001C40F7 /* HealthKitWriter.swift in Sources */, - 042023E226178860001C40F7 /* Extensions+HKCorrelation.swift in Sources */, - 042023FB26178860001C40F7 /* HealthKitManager.swift in Sources */, - 04CC38E426E37F970067ABFD /* Extensions+HKWorkoutEventType.swift in Sources */, - 0420241D26178860001C40F7 /* Harmonizable.swift in Sources */, - 0420240B26178860001C40F7 /* WorkoutConfiguration.swift in Sources */, - 040EFF2126E4CD0500D37F04 /* Extensions+HKCategoryValueContraceptive.swift in Sources */, - 0420241726178860001C40F7 /* DocumentType.swift in Sources */, - 0420240526178860001C40F7 /* Electrocardiogram.swift in Sources */, - 042023FE26178860001C40F7 /* Statistics.swift in Sources */, - 040EFF0B26E4C97500D37F04 /* Extensions+HKCategoryValue.swift in Sources */, - 0420240626178860001C40F7 /* WorkoutEvent.swift in Sources */, - 042023EF26178860001C40F7 /* Extensions+DateComponents.swift in Sources */, - 042023F426178860001C40F7 /* Extensions+HKWorkoutEvent.swift in Sources */, - 0420241126178860001C40F7 /* ActivitySummaryType.swift in Sources */, - 042023DE26178860001C40F7 /* Extensions+HKStatistics.swift in Sources */, - 0420241B26178860001C40F7 /* Payload.swift in Sources */, - 040EFF1B26E4CBD800D37F04 /* Extensions+HKCategoryValueAppetiteChanges.swift in Sources */, - 042023E426178860001C40F7 /* Extensions+HKFitzpatrickSkinType.swift in Sources */, - 042023EE26178860001C40F7 /* Extensions+HKQuantitiySample.swift in Sources */, - 0420241426178860001C40F7 /* SeriesType.swift in Sources */, - 040EFF1726E4CB2500D37F04 /* Extensions+HKCategoryValueSeverity.swift in Sources */, - 042023EA26178860001C40F7 /* Extensions+NSPredicate.swift in Sources */, - 0420241026178860001C40F7 /* CharacteristicType.swift in Sources */, - 0420240426178860001C40F7 /* DeletedObject.swift in Sources */, - 0420241C26178860001C40F7 /* UpdateFrequency.swift in Sources */, - 042023E026178860001C40F7 /* Extensions+String.swift in Sources */, - 0420241226178860001C40F7 /* QuantityType.swift in Sources */, - 040EFF1526E4CAE200D37F04 /* Extensions+HKCategoryValueLowCardioFitnessEvent.swift in Sources */, - 0420241A26178860001C40F7 /* ObjectType.swift in Sources */, - 042023E126178860001C40F7 /* Extensions+HKCategoryType.swift in Sources */, - 0420242026178860001C40F7 /* HealthKitReporter.swift in Sources */, - 042023E926178860001C40F7 /* Extensions+HKSample.swift in Sources */, - 042023F926178860001C40F7 /* ElectrocardiogramRetriever.swift in Sources */, - 042023F226178860001C40F7 /* Extensions+HKBiologicalSex.swift in Sources */, - 042023E726178860001C40F7 /* Extensions+HKElectrocardiogram.swift in Sources */, - 042023EC26178860001C40F7 /* Extensions+HKWheelchairUse.swift in Sources */, - 042023E626178860001C40F7 /* Extensions+HKActivitySummary.swift in Sources */, - 0420240326178860001C40F7 /* WorkoutRoute.swift in Sources */, - 040EFF1926E4CB8700D37F04 /* Extensions+HKCategoryValuePresence.swift in Sources */, - 042023E526178860001C40F7 /* Extensions+HKCategorySample.swift in Sources */, - 042023E826178860001C40F7 /* Extensions+HKQuantityType.swift in Sources */, - 042023E326178860001C40F7 /* Extensions+Double.swift in Sources */, - 04F6E1782715DADC00A63807 /* Extensions+HKHeartbeatSeriesSample.swift in Sources */, - 042023F126178860001C40F7 /* Extensions+HKWorkout.swift in Sources */, - 04F6E1762715D6B800A63807 /* HeartbeatSeries.swift in Sources */, - 0420241F26178860001C40F7 /* HealthKitError.swift in Sources */, - 0420240826178860001C40F7 /* Category.swift in Sources */, - 0420241E26178860001C40F7 /* PreferredUnit.swift in Sources */, - 042023DF26178860001C40F7 /* Extensions+HKWorkoutActivityType.swift in Sources */, - 0420240A26178860001C40F7 /* Device.swift in Sources */, - 042023DD26178860001C40F7 /* Extensions+HKBloodType.swift in Sources */, - 042023FF26178860001C40F7 /* Workout.swift in Sources */, - 042023F326178860001C40F7 /* Extensions+Dictionary.swift in Sources */, - 042023F826178860001C40F7 /* SeriesSampleRetriever.swift in Sources */, - 040EFF0926E4C91700D37F04 /* Extensions+HKCategoryValueSleepAnalysis.swift in Sources */, - 040EFF0F26E4C9FB00D37F04 /* Extensions+HKCategoryValueOvulationTestResult.swift in Sources */, - 0420241326178860001C40F7 /* CategoryType.swift in Sources */, - 0420240E26178860001C40F7 /* Original.swift in Sources */, - 042023DC26178860001C40F7 /* Extensions+HKWorkoutConfiguration.swift in Sources */, - 0420240126178860001C40F7 /* Sample.swift in Sources */, - 042023ED26178860001C40F7 /* Extensions+HKSourceRevision.swift in Sources */, - 0420240926178860001C40F7 /* Identifiable.swift in Sources */, - 0420240D26178860001C40F7 /* SourceRevision.swift in Sources */, - 0420241926178860001C40F7 /* CorrelationType.swift in Sources */, + 019CD4D6FD914C9DB5CC4890D4A82F36 /* Pods-HealthKitReporter_Tests-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 07D53EEA9B8D803C4C3D0F4B23EA9C92 /* Sources */ = { + B4800AF4BCB62F4DDA196B3430390D40 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 6F28EC06A500C967543B8E86760AE5E9 /* Pods-HealthKitReporter_Tests-dummy.m in Sources */, + C9941F0ABF71109D11C4BC874F1CDC0D /* Pods-HealthKitReporter_Example-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B9FDBFBE87365143F02801B094F7777F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3E6795A277D1ACDDBFC26912FC3950EE /* ActivitySummaryTests.swift in Sources */, + AC99DC4CD498172DCA0F1101F9CB1AD6 /* CategoryTests.swift in Sources */, + EA8B3BD7588E42A2DA08A40CC514BDCC /* CharacteristicTests.swift in Sources */, + AB612C2E12FCAAA03993F152F19D2E89 /* CorrelationTests.swift in Sources */, + EE58B4676A7806C9913ABABCC0D4350F /* DeletedObjectTests.swift in Sources */, + 8DFF2F882B6C1B982535857DFDF3AA57 /* DeviceTests.swift in Sources */, + D4A68B708717C9CA8010AC7EF5F7E358 /* ElectrocardiogramTests.swift in Sources */, + F425257EFC5840BCEC6D5F06D8486014 /* HealthKitReporterTests.swift in Sources */, + C671DDF5C71D89FDAECB2196032DC757 /* HeartbeatSeriesTests.swift in Sources */, + B066548AEB09F12F3B9C90D2EC881DF7 /* QuantityTests.swift in Sources */, + 6C4AB9516500B814B5CF21FBF2C602F1 /* SourceRevisionTests.swift in Sources */, + CA87DE6BAC9353325E52B827A518DD51 /* SourceTests.swift in Sources */, + CDBB74195DF3FADDA35B0AD1AD36A282 /* StatisticsTests.swift in Sources */, + 5F3B7021E8BB5A6E798FF957004973F5 /* WorkoutConfigurationTests.swift in Sources */, + F8FFD22B85640666C33325AD78FFF0F3 /* WorkoutEventTests.swift in Sources */, + EC8FBD3CC6A6C33B3B2593EDFE12C37D /* WorkoutRouteTests.swift in Sources */, + 9201CAC9BD32E93586C424EDE967F6A0 /* WorkoutTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 3B81A1703A3290BFD8875EA5F35FF447 /* PBXTargetDependency */ = { + 8A109F2D27CACCF9DD624F87B2CE634B /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = HealthKitReporter; target = 5A02BB0F1AC44F7E176E662038412466 /* HealthKitReporter */; - targetProxy = 1D86DB38B43E80AB41E39090DE8582C7 /* PBXContainerItemProxy */; + targetProxy = A93A4E42D5FFC2252F13989652DF8556 /* PBXContainerItemProxy */; }; - 7FBAEE0B17571BB78AA23BAC547A7B9F /* PBXTargetDependency */ = { + EB3966D0FC1AB9EDFC564AADC3E16444 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "Pods-HealthKitReporter_Example"; - target = 28111CA3729B131600777B0AE0E0AF79 /* Pods-HealthKitReporter_Example */; - targetProxy = 77B5177E471D03D84010CE70DB806746 /* PBXContainerItemProxy */; + name = HealthKitReporter; + target = 5A02BB0F1AC44F7E176E662038412466 /* HealthKitReporter */; + targetProxy = A6CE1C26B06BBBE9E59867969C8F82A1 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 1489C1908FDEE223F8D3293EED25BFC6 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 50AA0CA84AA46A85BDCFA91A07CA472E /* HealthKitReporter.release.xcconfig */; - buildSettings = { - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/HealthKitReporter/HealthKitReporter-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/HealthKitReporter/HealthKitReporter-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/HealthKitReporter/HealthKitReporter.modulemap"; - PRODUCT_BUNDLE_IDENTIFIER = com.kvs.HealthKitReporter; - PRODUCT_MODULE_NAME = HealthKitReporter; - PRODUCT_NAME = HealthKitReporter; - PROVISIONING_PROFILE_SPECIFIER = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SUPPORTS_MACCATALYST = NO; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 1EAC421CEF9CC511D722D78B25AAF101 /* Debug */ = { + 0B00D87BBB22F414A5C56374FEAC74CD /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D4755EC74B169D2FA28AC646D8EE2033 /* Pods-HealthKitReporter_Tests.debug.xcconfig */; + baseConfigurationReference = 10ED9239B0ED1C13D65048DF6C2EDD88 /* Pods-HealthKitReporter_Example.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; @@ -864,67 +1013,31 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-HealthKitReporter_Tests/Pods-HealthKitReporter_Tests-Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-HealthKitReporter_Tests/Pods-HealthKitReporter_Tests.modulemap"; + MODULEMAP_FILE = "Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "com.kvs.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Debug; - }; - 68EA34250F5B99E8AA34D4231BF90CB5 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 620026A50D6F3042580BA62B0F2A5E24 /* HealthKitReporter.debug.xcconfig */; - buildSettings = { - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/HealthKitReporter/HealthKitReporter-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/HealthKitReporter/HealthKitReporter-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/HealthKitReporter/HealthKitReporter.modulemap"; - PRODUCT_BUNDLE_IDENTIFIER = com.kvs.HealthKitReporter; - PRODUCT_MODULE_NAME = HealthKitReporter; - PRODUCT_NAME = HealthKitReporter; - PROVISIONING_PROFILE_SPECIFIER = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SUPPORTS_MACCATALYST = NO; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; + name = Release; }; - 8A0DC8E6BDF756EA8C1B41F72B158CFC /* Release */ = { + 119BB32ED22ADC9FC5E0CA8E16D910F9 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 10ED9239B0ED1C13D65048DF6C2EDD88 /* Pods-HealthKitReporter_Example.release.xcconfig */; + baseConfigurationReference = C1DF9C7E917631DB50FD5DEDE8CDA43A /* Pods-HealthKitReporter_Example.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; @@ -935,27 +1048,28 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; MODULEMAP_FILE = "Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "com.kvs.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Release; + name = Debug; }; - B0087CB4594321EF41619F3181FE120E /* Release */ = { + 25AD9454612BF454A1E3DC4CD4FA8C6D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -986,13 +1100,16 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; + DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_RELEASE=1", + "POD_CONFIGURATION_DEBUG=1", + "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -1002,21 +1119,160 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.0; - MARKETING_VERSION = 1.6.1; - MTL_ENABLE_DEBUG_INFO = NO; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; STRIP_INSTALLED_PRODUCT = NO; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; SYMROOT = "${SRCROOT}/../build"; }; + name = Debug; + }; + 3C5B097BAC935A7F178654E866B79270 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 09A91F461B623281D4F426E925D6B6BE /* HealthKitReporter.unit-tests.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGNING_ALLOWED = YES; + CODE_SIGNING_REQUIRED = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + GCC_PREFIX_HEADER = "Target Support Files/HealthKitReporter/HealthKitReporter-Unit-Tests-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/HealthKitReporter/HealthKitReporter-Unit-Tests-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + PRODUCT_NAME = "HealthKitReporter-Unit-Tests"; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.3; + }; + name = Debug; + }; + 54B0B2E2CBA6F418E3C7B2284AB51979 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B4665EC9F0AB7C6F5920DFFC6369A299 /* Pods-HealthKitReporter_Tests.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-HealthKitReporter_Tests/Pods-HealthKitReporter_Tests-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-HealthKitReporter_Tests/Pods-HealthKitReporter_Tests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 551AC7FB6C475746F9F1A57480EBFC7B /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1DA81DC75879F428CC7DD41B6ABAE326 /* HealthKitReporter.unit-tests.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGNING_ALLOWED = YES; + CODE_SIGNING_REQUIRED = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + GCC_PREFIX_HEADER = "Target Support Files/HealthKitReporter/HealthKitReporter-Unit-Tests-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/HealthKitReporter/HealthKitReporter-Unit-Tests-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + PRODUCT_NAME = "HealthKitReporter-Unit-Tests"; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.3; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 94F1225862AF0169A83F67DC55860D44 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = FA34A422D5D91CA343375D9F5656E0C9 /* HealthKitReporter.debug.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/HealthKitReporter/HealthKitReporter-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/HealthKitReporter/HealthKitReporter-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/HealthKitReporter/HealthKitReporter.modulemap"; + PRODUCT_MODULE_NAME = HealthKitReporter; + PRODUCT_NAME = HealthKitReporter; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.3; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + B0AEF90EA56C448AE85C2F6609AEFD35 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 39C648D3DC1753ED463E13801E3D76AD /* HealthKitReporter.release.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/HealthKitReporter/HealthKitReporter-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/HealthKitReporter/HealthKitReporter-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/HealthKitReporter/HealthKitReporter.modulemap"; + PRODUCT_MODULE_NAME = HealthKitReporter; + PRODUCT_NAME = HealthKitReporter; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.3; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; name = Release; }; - B8BCBD0110C2658BB5DAADB9B7D97B92 /* Debug */ = { + CA547D2C7E9A8A153DC2B27FBE00B112 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -1047,16 +1303,13 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_DEBUG=1", - "DEBUG=1", + "POD_CONFIGURATION_RELEASE=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -1066,25 +1319,21 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.0; - MARKETING_VERSION = 1.6.1; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; STRIP_INSTALLED_PRODUCT = NO; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 5.0; SYMROOT = "${SRCROOT}/../build"; }; - name = Debug; + name = Release; }; - CAA31E07611B485FBC33080EEDCFD920 /* Release */ = { + CAD8FCDF67C365D4079EB470F2E6D0F6 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = B4665EC9F0AB7C6F5920DFFC6369A299 /* Pods-HealthKitReporter_Tests.release.xcconfig */; + baseConfigurationReference = D4755EC74B169D2FA28AC646D8EE2033 /* Pods-HealthKitReporter_Tests.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; @@ -1095,46 +1344,14 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "Target Support Files/Pods-HealthKitReporter_Tests/Pods-HealthKitReporter_Tests-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; MODULEMAP_FILE = "Target Support Files/Pods-HealthKitReporter_Tests/Pods-HealthKitReporter_Tests.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "com.kvs.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - D2E3F1A5542831AB44438FDD5694CD31 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = C1DF9C7E917631DB50FD5DEDE8CDA43A /* Pods-HealthKitReporter_Example.debug.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "com.kvs.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; @@ -1147,20 +1364,20 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 12BC7DE726408235B7E6481391999AE1 /* Build configuration list for PBXNativeTarget "HealthKitReporter" */ = { + 29C84D345321537916857512219F2695 /* Build configuration list for PBXNativeTarget "Pods-HealthKitReporter_Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 68EA34250F5B99E8AA34D4231BF90CB5 /* Debug */, - 1489C1908FDEE223F8D3293EED25BFC6 /* Release */, + CAD8FCDF67C365D4079EB470F2E6D0F6 /* Debug */, + 54B0B2E2CBA6F418E3C7B2284AB51979 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 462C3705D1ECE509B74B839B20B64CFC /* Build configuration list for PBXNativeTarget "Pods-HealthKitReporter_Example" */ = { + 2BF9C5E43072C436F6AF1BAD30FD34E6 /* Build configuration list for PBXNativeTarget "HealthKitReporter" */ = { isa = XCConfigurationList; buildConfigurations = ( - D2E3F1A5542831AB44438FDD5694CD31 /* Debug */, - 8A0DC8E6BDF756EA8C1B41F72B158CFC /* Release */, + 94F1225862AF0169A83F67DC55860D44 /* Debug */, + B0AEF90EA56C448AE85C2F6609AEFD35 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -1168,17 +1385,26 @@ 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( - B8BCBD0110C2658BB5DAADB9B7D97B92 /* Debug */, - B0087CB4594321EF41619F3181FE120E /* Release */, + 25AD9454612BF454A1E3DC4CD4FA8C6D /* Debug */, + CA547D2C7E9A8A153DC2B27FBE00B112 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B203D0872371CAF5CA06C23E4B167704 /* Build configuration list for PBXNativeTarget "Pods-HealthKitReporter_Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 119BB32ED22ADC9FC5E0CA8E16D910F9 /* Debug */, + 0B00D87BBB22F414A5C56374FEAC74CD /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 909FC5628D7365862B57B291F08245AA /* Build configuration list for PBXNativeTarget "Pods-HealthKitReporter_Tests" */ = { + BF6E6487B3C43FA0FAA05D5B638ED4BB /* Build configuration list for PBXNativeTarget "HealthKitReporter-Unit-Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 1EAC421CEF9CC511D722D78B25AAF101 /* Debug */, - CAA31E07611B485FBC33080EEDCFD920 /* Release */, + 3C5B097BAC935A7F178654E866B79270 /* Debug */, + 551AC7FB6C475746F9F1A57480EBFC7B /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/Example/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-HealthKitReporter_Tests.xcscheme b/Example/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-HealthKitReporter_Tests.xcscheme new file mode 100644 index 0000000..6d29845 --- /dev/null +++ b/Example/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-HealthKitReporter_Tests.xcscheme @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter-Info.plist b/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter-Info.plist index 72caab8..07e0ad9 100644 --- a/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter-Info.plist +++ b/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter-Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) + ${PRODUCT_BUNDLE_IDENTIFIER} CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - $(MARKETING_VERSION) + 3.1.0 CFBundleSignature ???? CFBundleVersion diff --git a/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter-Unit-Tests-Info.plist b/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter-Unit-Tests-Info.plist new file mode 100644 index 0000000..45f6ca7 --- /dev/null +++ b/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter-Unit-Tests-Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSPrincipalClass + + + diff --git a/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter-Unit-Tests-frameworks.sh b/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter-Unit-Tests-frameworks.sh new file mode 100755 index 0000000..2c7164c --- /dev/null +++ b/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter-Unit-Tests-frameworks.sh @@ -0,0 +1,186 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +function on_error { + echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" +} +trap 'on_error $LINENO' ERR + +if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then + # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy + # frameworks to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" +mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" +SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" +BCSYMBOLMAP_DIR="BCSymbolMaps" + + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +# Copies and strips a vendored framework +install_framework() +{ + if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then + local source="${BUILT_PRODUCTS_DIR}/$1" + elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then + local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" + elif [ -r "$1" ]; then + local source="$1" + fi + + local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + + if [ -L "${source}" ]; then + echo "Symlinked..." + source="$(readlink "${source}")" + fi + + if [ -d "${source}/${BCSYMBOLMAP_DIR}" ]; then + # Locate and install any .bcsymbolmaps if present, and remove them from the .framework before the framework is copied + find "${source}/${BCSYMBOLMAP_DIR}" -name "*.bcsymbolmap"|while read f; do + echo "Installing $f" + install_bcsymbolmap "$f" "$destination" + rm "$f" + done + rmdir "${source}/${BCSYMBOLMAP_DIR}" + fi + + # Use filter instead of exclude so missing patterns don't throw errors. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + + local basename + basename="$(basename -s .framework "$1")" + binary="${destination}/${basename}.framework/${basename}" + + if ! [ -r "$binary" ]; then + binary="${destination}/${basename}" + elif [ -L "${binary}" ]; then + echo "Destination binary is symlinked..." + dirname="$(dirname "${binary}")" + binary="${dirname}/$(readlink "${binary}")" + fi + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then + strip_invalid_archs "$binary" + fi + + # Resign the code if required by the build settings to avoid unstable apps + code_sign_if_enabled "${destination}/$(basename "$1")" + + # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. + if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then + local swift_runtime_libs + swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u) + for lib in $swift_runtime_libs; do + echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" + rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" + code_sign_if_enabled "${destination}/${lib}" + done + fi +} +# Copies and strips a vendored dSYM +install_dsym() { + local source="$1" + warn_missing_arch=${2:-true} + if [ -r "$source" ]; then + # Copy the dSYM into the targets temp dir. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" + + local basename + basename="$(basename -s .dSYM "$source")" + binary_name="$(ls "$source/Contents/Resources/DWARF")" + binary="${DERIVED_FILES_DIR}/${basename}.dSYM/Contents/Resources/DWARF/${binary_name}" + + # Strip invalid architectures from the dSYM. + if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then + strip_invalid_archs "$binary" "$warn_missing_arch" + fi + if [[ $STRIP_BINARY_RETVAL == 0 ]]; then + # Move the stripped file into its final destination. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.dSYM" "${DWARF_DSYM_FOLDER_PATH}" + else + # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + mkdir -p "${DWARF_DSYM_FOLDER_PATH}" + touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.dSYM" + fi + fi +} + +# Used as a return value for each invocation of `strip_invalid_archs` function. +STRIP_BINARY_RETVAL=0 + +# Strip invalid architectures +strip_invalid_archs() { + binary="$1" + warn_missing_arch=${2:-true} + # Get architectures for current target binary + binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" + # Intersect them with the architectures we are building for + intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" + # If there are no archs supported by this binary then warn the user + if [[ -z "$intersected_archs" ]]; then + if [[ "$warn_missing_arch" == "true" ]]; then + echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." + fi + STRIP_BINARY_RETVAL=1 + return + fi + stripped="" + for arch in $binary_archs; do + if ! [[ "${ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$binary" "$binary" + stripped="$stripped $arch" + fi + done + if [[ "$stripped" ]]; then + echo "Stripped $binary of architectures:$stripped" + fi + STRIP_BINARY_RETVAL=0 +} + +# Copies the bcsymbolmap files of a vendored framework +install_bcsymbolmap() { + local bcsymbolmap_path="$1" + local destination="${BUILT_PRODUCTS_DIR}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" +} + +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identity + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" + + if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + code_sign_cmd="$code_sign_cmd &" + fi + echo "$code_sign_cmd" + eval "$code_sign_cmd" + fi +} + +if [[ "$CONFIGURATION" == "Debug" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/HealthKitReporter/HealthKitReporter.framework" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/HealthKitReporter/HealthKitReporter.framework" +fi +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter-Unit-Tests-prefix.pch b/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter-Unit-Tests-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter-Unit-Tests-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter.debug.xcconfig b/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter.debug.xcconfig index ff0c9cc..dc492f1 100644 --- a/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter.debug.xcconfig +++ b/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter.debug.xcconfig @@ -1,10 +1,13 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/HealthKitReporter GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_ROOT = ${SRCROOT} PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. -PRODUCT_BUNDLE_IDENTIFIER = com.kvs.${PRODUCT_NAME:rfc1034identifier} +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} SKIP_INSTALL = YES USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter.release.xcconfig b/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter.release.xcconfig index ff0c9cc..dc492f1 100644 --- a/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter.release.xcconfig +++ b/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter.release.xcconfig @@ -1,10 +1,13 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/HealthKitReporter GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_ROOT = ${SRCROOT} PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. -PRODUCT_BUNDLE_IDENTIFIER = com.kvs.${PRODUCT_NAME:rfc1034identifier} +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} SKIP_INSTALL = YES USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter.unit-tests.debug.xcconfig b/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter.unit-tests.debug.xcconfig new file mode 100644 index 0000000..f606803 --- /dev/null +++ b/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter.unit-tests.debug.xcconfig @@ -0,0 +1,15 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/HealthKitReporter" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift "$(PLATFORM_DIR)/Developer/Library/Frameworks" '@executable_path/Frameworks' '@loader_path/Frameworks' +LIBRARY_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift +OTHER_LDFLAGS = $(inherited) -ObjC -framework "HealthKitReporter" +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter.unit-tests.release.xcconfig b/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter.unit-tests.release.xcconfig new file mode 100644 index 0000000..f606803 --- /dev/null +++ b/Example/Pods/Target Support Files/HealthKitReporter/HealthKitReporter.unit-tests.release.xcconfig @@ -0,0 +1,15 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/HealthKitReporter" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift "$(PLATFORM_DIR)/Developer/Library/Frameworks" '@executable_path/Frameworks' '@loader_path/Frameworks' +LIBRARY_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift +OTHER_LDFLAGS = $(inherited) -ObjC -framework "HealthKitReporter" +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Example/Pods/Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example-Info.plist b/Example/Pods/Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example-Info.plist index 1f91650..2243fe6 100644 --- a/Example/Pods/Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example-Info.plist +++ b/Example/Pods/Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example-Info.plist @@ -2,25 +2,25 @@ - CFBundleDevelopmentRegion - en - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIdentifier - ${PRODUCT_BUNDLE_IDENTIFIER} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - FMWK - CFBundleShortVersionString - $(MARKETING_VERSION) - CFBundleSignature - ???? - CFBundleVersion - ${CURRENT_PROJECT_VERSION} - NSPrincipalClass - + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + diff --git a/Example/Pods/Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example-acknowledgements.plist b/Example/Pods/Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example-acknowledgements.plist index 4f6a84a..57f17d0 100644 --- a/Example/Pods/Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example-acknowledgements.plist +++ b/Example/Pods/Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example-acknowledgements.plist @@ -17,7 +17,7 @@ Copyright (c) 2020 Victor Kachalov <victorkachalov@gmail.com> Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal +of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is @@ -26,7 +26,7 @@ furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER diff --git a/Example/Pods/Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example-frameworks.sh b/Example/Pods/Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example-frameworks.sh index bdaf6ef..2c7164c 100755 --- a/Example/Pods/Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example-frameworks.sh +++ b/Example/Pods/Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example-frameworks.sh @@ -19,9 +19,8 @@ mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" +BCSYMBOLMAP_DIR="BCSymbolMaps" -# Used as a return value for each invocation of `strip_invalid_archs` function. -STRIP_BINARY_RETVAL=0 # This protects against multiple targets copying the same framework dependency at the same time. The solution # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html @@ -45,6 +44,16 @@ install_framework() source="$(readlink "${source}")" fi + if [ -d "${source}/${BCSYMBOLMAP_DIR}" ]; then + # Locate and install any .bcsymbolmaps if present, and remove them from the .framework before the framework is copied + find "${source}/${BCSYMBOLMAP_DIR}" -name "*.bcsymbolmap"|while read f; do + echo "Installing $f" + install_bcsymbolmap "$f" "$destination" + rm "$f" + done + rmdir "${source}/${BCSYMBOLMAP_DIR}" + fi + # Use filter instead of exclude so missing patterns don't throw errors. echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" @@ -80,7 +89,6 @@ install_framework() done fi } - # Copies and strips a vendored dSYM install_dsym() { local source="$1" @@ -95,44 +103,24 @@ install_dsym() { binary_name="$(ls "$source/Contents/Resources/DWARF")" binary="${DERIVED_FILES_DIR}/${basename}.dSYM/Contents/Resources/DWARF/${binary_name}" - # Strip invalid architectures so "fat" simulator / device frameworks work on device + # Strip invalid architectures from the dSYM. if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then strip_invalid_archs "$binary" "$warn_missing_arch" fi - - if [[ $STRIP_BINARY_RETVAL == 1 ]]; then + if [[ $STRIP_BINARY_RETVAL == 0 ]]; then # Move the stripped file into its final destination. echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.dSYM" "${DWARF_DSYM_FOLDER_PATH}" else # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + mkdir -p "${DWARF_DSYM_FOLDER_PATH}" touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.dSYM" fi fi } -# Copies the bcsymbolmap files of a vendored framework -install_bcsymbolmap() { - local bcsymbolmap_path="$1" - local destination="${BUILT_PRODUCTS_DIR}" - echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" - rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" -} - -# Signs a framework with the provided identity -code_sign_if_enabled() { - if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then - # Use the current code_sign_identity - echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" - local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" - - if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then - code_sign_cmd="$code_sign_cmd &" - fi - echo "$code_sign_cmd" - eval "$code_sign_cmd" - fi -} +# Used as a return value for each invocation of `strip_invalid_archs` function. +STRIP_BINARY_RETVAL=0 # Strip invalid architectures strip_invalid_archs() { @@ -147,7 +135,7 @@ strip_invalid_archs() { if [[ "$warn_missing_arch" == "true" ]]; then echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." fi - STRIP_BINARY_RETVAL=0 + STRIP_BINARY_RETVAL=1 return fi stripped="" @@ -161,40 +149,31 @@ strip_invalid_archs() { if [[ "$stripped" ]]; then echo "Stripped $binary of architectures:$stripped" fi - STRIP_BINARY_RETVAL=1 + STRIP_BINARY_RETVAL=0 } -install_artifact() { - artifact="$1" - base="$(basename "$artifact")" - case $base in - *.framework) - install_framework "$artifact" - ;; - *.dSYM) - # Suppress arch warnings since XCFrameworks will include many dSYM files - install_dsym "$artifact" "false" - ;; - *.bcsymbolmap) - install_bcsymbolmap "$artifact" - ;; - *) - echo "error: Unrecognized artifact "$artifact"" - ;; - esac +# Copies the bcsymbolmap files of a vendored framework +install_bcsymbolmap() { + local bcsymbolmap_path="$1" + local destination="${BUILT_PRODUCTS_DIR}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" } -copy_artifacts() { - file_list="$1" - while read artifact; do - install_artifact "$artifact" - done <$file_list -} +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identity + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" -ARTIFACT_LIST_FILE="${BUILT_PRODUCTS_DIR}/cocoapods-artifacts-${CONFIGURATION}.txt" -if [ -r "${ARTIFACT_LIST_FILE}" ]; then - copy_artifacts "${ARTIFACT_LIST_FILE}" -fi + if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + code_sign_cmd="$code_sign_cmd &" + fi + echo "$code_sign_cmd" + eval "$code_sign_cmd" + fi +} if [[ "$CONFIGURATION" == "Debug" ]]; then install_framework "${BUILT_PRODUCTS_DIR}/HealthKitReporter/HealthKitReporter.framework" diff --git a/Example/Pods/Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example.debug.xcconfig b/Example/Pods/Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example.debug.xcconfig index e2727db..f24d980 100644 --- a/Example/Pods/Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example.debug.xcconfig +++ b/Example/Pods/Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example.debug.xcconfig @@ -1,12 +1,15 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/HealthKitReporter" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/HealthKitReporter/HealthKitReporter.framework/Headers" -LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' +LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift OTHER_LDFLAGS = $(inherited) -framework "HealthKitReporter" OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_ROOT = ${SRCROOT}/Pods +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Example/Pods/Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example.release.xcconfig b/Example/Pods/Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example.release.xcconfig index e2727db..f24d980 100644 --- a/Example/Pods/Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example.release.xcconfig +++ b/Example/Pods/Target Support Files/Pods-HealthKitReporter_Example/Pods-HealthKitReporter_Example.release.xcconfig @@ -1,12 +1,15 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/HealthKitReporter" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/HealthKitReporter/HealthKitReporter.framework/Headers" -LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' +LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift OTHER_LDFLAGS = $(inherited) -framework "HealthKitReporter" OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_ROOT = ${SRCROOT}/Pods +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Example/Pods/Target Support Files/Pods-HealthKitReporter_Tests/Pods-HealthKitReporter_Tests-Info.plist b/Example/Pods/Target Support Files/Pods-HealthKitReporter_Tests/Pods-HealthKitReporter_Tests-Info.plist index 1f91650..2243fe6 100644 --- a/Example/Pods/Target Support Files/Pods-HealthKitReporter_Tests/Pods-HealthKitReporter_Tests-Info.plist +++ b/Example/Pods/Target Support Files/Pods-HealthKitReporter_Tests/Pods-HealthKitReporter_Tests-Info.plist @@ -2,25 +2,25 @@ - CFBundleDevelopmentRegion - en - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIdentifier - ${PRODUCT_BUNDLE_IDENTIFIER} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - FMWK - CFBundleShortVersionString - $(MARKETING_VERSION) - CFBundleSignature - ???? - CFBundleVersion - ${CURRENT_PROJECT_VERSION} - NSPrincipalClass - + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + diff --git a/Example/Pods/Target Support Files/Pods-HealthKitReporter_Tests/Pods-HealthKitReporter_Tests.debug.xcconfig b/Example/Pods/Target Support Files/Pods-HealthKitReporter_Tests/Pods-HealthKitReporter_Tests.debug.xcconfig index aaec2f1..26f2c77 100644 --- a/Example/Pods/Target Support Files/Pods-HealthKitReporter_Tests/Pods-HealthKitReporter_Tests.debug.xcconfig +++ b/Example/Pods/Target Support Files/Pods-HealthKitReporter_Tests/Pods-HealthKitReporter_Tests.debug.xcconfig @@ -1,9 +1,8 @@ -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/HealthKitReporter" +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/HealthKitReporter/HealthKitReporter.framework/Headers" -OTHER_LDFLAGS = $(inherited) -framework "HealthKitReporter" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_ROOT = ${SRCROOT}/Pods +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Example/Pods/Target Support Files/Pods-HealthKitReporter_Tests/Pods-HealthKitReporter_Tests.release.xcconfig b/Example/Pods/Target Support Files/Pods-HealthKitReporter_Tests/Pods-HealthKitReporter_Tests.release.xcconfig index aaec2f1..26f2c77 100644 --- a/Example/Pods/Target Support Files/Pods-HealthKitReporter_Tests/Pods-HealthKitReporter_Tests.release.xcconfig +++ b/Example/Pods/Target Support Files/Pods-HealthKitReporter_Tests/Pods-HealthKitReporter_Tests.release.xcconfig @@ -1,9 +1,8 @@ -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/HealthKitReporter" +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/HealthKitReporter/HealthKitReporter.framework/Headers" -OTHER_LDFLAGS = $(inherited) -framework "HealthKitReporter" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_ROOT = ${SRCROOT}/Pods +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Example/Tests/Tests.swift b/Example/Tests/Tests.swift index 54174aa..2c7fa47 100644 --- a/Example/Tests/Tests.swift +++ b/Example/Tests/Tests.swift @@ -1,5 +1,4 @@ import XCTest -import HealthKitReporter class Tests: XCTestCase { override func setUp() { diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..4e43ba3 --- /dev/null +++ b/Gemfile @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +source 'https://rubygems.org' + +ruby '~> 2.6.0' + +gem 'cocoapods', '~> 1.11.2' +gem 'fastlane', '~> 2.178' +gem 'xcode-install', '~> 2.6.8' +gem 'xcpretty-actions-formatter', '~> 0.1.2' diff --git a/HealthKitReporter.podspec b/HealthKitReporter.podspec index e53a1ac..cdbfb11 100644 --- a/HealthKitReporter.podspec +++ b/HealthKitReporter.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'HealthKitReporter' - s.version = '1.6.1' + s.version = '3.1.0' s.summary = 'HealthKitReporter. A wrapper for HealthKit framework.' s.swift_versions = '5.3' s.description = 'Helps to write or read data from Apple Health via HealthKit framework.' @@ -20,4 +20,8 @@ Pod::Spec.new do |s| s.platform = :ios, '9.0' s.ios.deployment_target = '9.0' s.source_files = 'Sources/**/*' + + s.test_spec 'Tests' do |t| + t.source_files = 'Tests/*.swift' + end end diff --git a/README.md b/README.md index a366b01..a9e24aa 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,11 @@ In addition you can write your own HealthKit objects using Codable wrappe ### Preparation -At first in your app's entitlements select HealthKit. and in your app's info.plist file add permissions: +At first in your app's entitlements select HealthKit. +If you want to read Clinical Records then also check "Clinical Health Records" under Health Kit. +***NOTE:*** *You can only tick the "Clinical Health Records" checkmark if your development team has a paid Apple developer subscription. To test on a real device, or to publish your application, you will need a paid Apple subscription, but you can still test on the iOS simulator without a subscription by setting the Development Team to None.* + +Then in your app's info.plist file add permissions: ```xml NSHealthShareUsageDescription @@ -28,6 +32,14 @@ If you plan to use **WorkoutRoute** **Series** please provide additionally CoreL WHY_YOU_NEED_TO_SHARE_LOCATION ``` +If you plan to read **Clinical Records** please provide additionally: + +```xml +NSHealthClinicalHealthRecordsShareUsageDescription +WHY_YOU_NEED_TO_SHARE_DATA +``` + + ### Common usage You create a HealthKitReporter instance surrounded by do catch block. If Apple Health is not supported by the device (i.e. iPad) the catch block will be called. @@ -47,7 +59,7 @@ In examples below every operation is hapenning iside authorization block. It is ### Reading Data Create a HealthKitReporter instance. -Authorize deisred types to read, like step count. +Authorize desired types to read, like step count. If authorization was successfull (the authorization window was shown) call sample query with type step count to create a **Query** object. @@ -132,9 +144,12 @@ Here is a sample response for steps: ``` ### Writing Data + +***NOTE:*** *Clinical Records are read only, Health Kit does not allow writing any data to Clinical Records.* + Create a HealthKitReporter instance. -Authorize deisred types to write, like step count. +Authorize desired types to write, like step count. You may call manager's preferredUnits(for: ) function to pass units (for Quantity Types). @@ -225,7 +240,7 @@ reporter.manager.preferredUnits(for: [.stepCount]) { (dictionary, error) in Create a HealthKitReporter instance. -Authorize deisred types to read/write, like step count and sleep analysis. +Authorize desired types to read/write, like step count and sleep analysis. You might create an App which will be called every time by HealthKit, and receive notifications, that some data was changed in HealthKit depending on frequency. But keep in mind that sometimes the desired frequency you set cannot be fulfilled by HealthKit. @@ -305,7 +320,7 @@ pod 'HealthKitReporter' or ```ruby -pod 'HealthKitReporter', '~> 1.6.1' +pod 'HealthKitReporter', '~> 3.1.0' ``` ### Swift Package Manager @@ -315,7 +330,7 @@ To install it, simply add the following lines to your Package.swift file ```swift dependencies: [ - .package(url: "https://github.com/VictorKachalov/HealthKitReporter.git", from: "1.6.1") + .package(url: "https://github.com/VictorKachalov/HealthKitReporter.git", from: "3.1.0") ] ``` @@ -324,7 +339,7 @@ dependencies: [ Add the line in your cartfile ```ruby -github "VictorKachalov/HealthKitReporter" "1.6.1" +github "VictorKachalov/HealthKitReporter" "3.1.0" ``` ## Author @@ -335,7 +350,5 @@ Victor Kachalov, victorkachalov@gmail.com HealthKitReporter is available under the MIT license. See the LICENSE file for more info. -## Donation -If you think that my repo helped you to solve the issues you struggle with, please don't be shy and donate :-) - -[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/paypalme/VictorKachalov/5EUR) +## Sponsorhip +If you think that my repo helped you to solve the issues you struggle with, please don't be shy and sponsor :-) diff --git a/Sources/Decorator/Extensions+Dictionary.swift b/Sources/Decorator/Extensions+Dictionary.swift index 9bc0912..755346e 100644 --- a/Sources/Decorator/Extensions+Dictionary.swift +++ b/Sources/Decorator/Extensions+Dictionary.swift @@ -5,7 +5,6 @@ // Created by Victor on 13.11.20. // -import Foundation import HealthKit public extension Dictionary where Key == String, Value == NSPredicate { @@ -54,3 +53,9 @@ public extension Dictionary where Key == String, Value == NSPredicate { return samplePredicates } } + +public extension Dictionary where Key == String, Value == Any { + var asMetadata: Metadata? { + try? Metadata.make(from: self) + } +} diff --git a/Sources/Decorator/Extensions+Encodable.swift b/Sources/Decorator/Extensions+Encodable.swift index 75347b4..e7ee59a 100644 --- a/Sources/Decorator/Extensions+Encodable.swift +++ b/Sources/Decorator/Extensions+Encodable.swift @@ -11,6 +11,7 @@ public extension Encodable { func encoded() throws -> String { let encoder = JSONEncoder() encoder.outputFormatting = .prettyPrinted + encoder.nonConformingFloatEncodingStrategy = .convertToString(positiveInfinity: Double.infinity.description, negativeInfinity: Double.infinity.description, nan: "-500.0") let data = try encoder.encode(self) guard let string = String(data: data, encoding: .utf8) else { throw HealthKitError.badEncoding("Impossible to encode: \(self)") diff --git a/Sources/Decorator/Extensions+HKActivityMoveMode.swift b/Sources/Decorator/Extensions+HKActivityMoveMode.swift index c1f2f3b..2e8fc90 100644 --- a/Sources/Decorator/Extensions+HKActivityMoveMode.swift +++ b/Sources/Decorator/Extensions+HKActivityMoveMode.swift @@ -5,11 +5,10 @@ // Created by Victor Kachalov on 27.01.21. // -import Foundation import HealthKit @available(iOS 14.0, *) -extension HKActivityMoveMode: CustomStringConvertible { +extension HKActivityMoveMode: @retroactive CustomStringConvertible { public var description: String { switch self { case .activeEnergy: diff --git a/Sources/Decorator/Extensions+HKActivitySummary.swift b/Sources/Decorator/Extensions+HKActivitySummary.swift index 7908d8d..bfbac78 100644 --- a/Sources/Decorator/Extensions+HKActivitySummary.swift +++ b/Sources/Decorator/Extensions+HKActivitySummary.swift @@ -5,7 +5,6 @@ // Created by Victor on 24.09.20. // -import Foundation import HealthKit @available(iOS 9.3, *) diff --git a/Sources/Decorator/Extensions+HKBiologicalSex.swift b/Sources/Decorator/Extensions+HKBiologicalSex.swift index c0f33c8..ba2c5af 100644 --- a/Sources/Decorator/Extensions+HKBiologicalSex.swift +++ b/Sources/Decorator/Extensions+HKBiologicalSex.swift @@ -5,10 +5,9 @@ // Created by Victor on 15.09.20. // -import Foundation import HealthKit -extension HKBiologicalSex: CustomStringConvertible { +extension HKBiologicalSex: @retroactive CustomStringConvertible { public var description: String { switch self { case .notSet: diff --git a/Sources/Decorator/Extensions+HKBloodType.swift b/Sources/Decorator/Extensions+HKBloodType.swift index 318336a..4170ff4 100644 --- a/Sources/Decorator/Extensions+HKBloodType.swift +++ b/Sources/Decorator/Extensions+HKBloodType.swift @@ -5,10 +5,9 @@ // Created by Victor on 15.09.20. // -import Foundation import HealthKit -extension HKBloodType: CustomStringConvertible { +extension HKBloodType: @retroactive CustomStringConvertible { public var description: String { switch self { case .notSet: diff --git a/Sources/Decorator/Extensions+HKCategorySample.swift b/Sources/Decorator/Extensions+HKCategorySample.swift index f4b136a..db3f9a4 100644 --- a/Sources/Decorator/Extensions+HKCategorySample.swift +++ b/Sources/Decorator/Extensions+HKCategorySample.swift @@ -5,7 +5,6 @@ // Created by Victor on 15.09.20. // -import Foundation import HealthKit extension HKCategorySample: Harmonizable { @@ -32,7 +31,20 @@ extension HKCategorySample: Harmonizable { description = value.description detail = value.detail } - case .sexualActivity: + case .intermenstrualBleeding, + .mindfulSession, + .highHeartRateEvent, + .lowHeartRateEvent, + .irregularHeartRhythmEvent, + .toothbrushingEvent, + .pregnancy, + .lactation, + .sexualActivity, + .handwashingEvent, + .persistentIntermenstrualBleeding, + .prolongedMenstrualPeriods, + .irregularMenstrualCycles, + .infrequentMenstrualCycles: if let value = HKCategoryValue(rawValue: value) { description = value.description detail = value.detail @@ -57,46 +69,7 @@ extension HKCategorySample: Harmonizable { description = value.description detail = value.detail } - case .intermenstrualBleeding: - if let value = HKCategoryValue(rawValue: value) { - description = value.description - detail = value.detail - } - case .mindfulSession: - if let value = HKCategoryValue(rawValue: value) { - description = value.description - detail = value.detail - } - case .highHeartRateEvent: - if let value = HKCategoryValue(rawValue: value) { - description = value.description - detail = value.detail - } - case .lowHeartRateEvent: - if let value = HKCategoryValue(rawValue: value) { - description = value.description - detail = value.detail - } - case .irregularHeartRhythmEvent: - if let value = HKCategoryValue(rawValue: value) { - description = value.description - detail = value.detail - } - case .toothbrushingEvent: - if let value = HKCategoryValue(rawValue: value) { - description = value.description - detail = value.detail - } - case .pregnancy: - if let value = HKCategoryValue(rawValue: value) { - description = value.description - detail = value.detail - } - case .lactation: - if let value = HKCategoryValue(rawValue: value) { - description = value.description - detail = value.detail - } + case .contraceptive: if #available(iOS 14.3, *) { if let value = HKCategoryValueContraceptive(rawValue: value) { @@ -130,11 +103,6 @@ extension HKCategorySample: Harmonizable { "\(type) is not available for the current iOS" ) } - case .handwashingEvent: - if let value = HKCategoryValue(rawValue: value) { - description = value.description - detail = value.detail - } case .lowCardioFitnessEvent: if #available(iOS 14.3, *) { if let value = HKCategoryValueLowCardioFitnessEvent(rawValue: value) { @@ -146,28 +114,6 @@ extension HKCategorySample: Harmonizable { "\(type) is not available for the current iOS" ) } - case .abdominalCramps: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .acne: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } case .appetiteChanges: if #available(iOS 13.6, *) { if let value = HKCategoryValueAppetiteChanges(rawValue: value) { @@ -179,249 +125,44 @@ extension HKCategorySample: Harmonizable { "\(type) is not available for the current iOS" ) } - case .bladderIncontinence: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .bloating: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .breastPain: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .chestTightnessOrPain: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .chills: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .constipation: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .coughing: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .diarrhea: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .dizziness: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .drySkin: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .fainting: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .fatigue: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .fever: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .generalizedBodyAche: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .hairLoss: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .headache: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .heartburn: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .hotFlashes: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .lossOfSmell: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .lossOfTaste: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .lowerBackPain: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .memoryLapse: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .moodChanges: + case .abdominalCramps, + .acne, + .bladderIncontinence, + .bloating, + .breastPain, + .chestTightnessOrPain, + .chills, + .constipation, + .coughing, + .diarrhea, + .dizziness, + .drySkin, + .fainting, + .fatigue, + .fever, + .generalizedBodyAche, + .hairLoss, + .headache, + .heartburn, + .hotFlashes, + .lossOfSmell, + .lossOfTaste, + .lowerBackPain, + .memoryLapse, + .moodChanges, + .nausea, + .nightSweats, + .pelvicPain, + .rapidPoundingOrFlutteringHeartbeat, + .runnyNose, + .shortnessOfBreath, + .sinusCongestion, + .skippedHeartbeat, + .sleepChanges, + .soreThroat, + .vaginalDryness, + .vomiting, + .wheezing: if #available(iOS 13.6, *) { if let value = HKCategoryValuePresence(rawValue: value) { description = value.description @@ -432,9 +173,9 @@ extension HKCategorySample: Harmonizable { "\(type) is not available for the current iOS" ) } - case .nausea: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { + case .pregnancyTestResult: + if #available(iOS 15.0, *) { + if let value = HKCategoryValuePregnancyTestResult(rawValue: value) { description = value.description detail = value.detail } @@ -443,9 +184,9 @@ extension HKCategorySample: Harmonizable { "\(type) is not available for the current iOS" ) } - case .nightSweats: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { + case .progesteroneTestResult: + if #available(iOS 15.0, *) { + if let value = HKCategoryValueProgesteroneTestResult(rawValue: value) { description = value.description detail = value.detail } @@ -454,119 +195,9 @@ extension HKCategorySample: Harmonizable { "\(type) is not available for the current iOS" ) } - case .pelvicPain: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .rapidPoundingOrFlutteringHeartbeat: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .runnyNose: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .shortnessOfBreath: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .sinusCongestion: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .skippedHeartbeat: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .sleepChanges: - if #available(iOS 13.6, *) { - if let value = HKCategoryValuePresence(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .soreThroat: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .vaginalDryness: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .vomiting: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { - description = value.description - detail = value.detail - } - } else { - throw HealthKitError.notAvailable( - "\(type) is not available for the current iOS" - ) - } - case .wheezing: - if #available(iOS 13.6, *) { - if let value = HKCategoryValueSeverity(rawValue: value) { + case .appleWalkingSteadinessEvent: + if #available(iOS 15.0, *) { + if let value = HKCategoryValueAppleWalkingSteadinessEvent(rawValue: value) { description = value.description detail = value.detail } @@ -584,7 +215,7 @@ extension HKCategorySample: Harmonizable { value: value, description: description, detail: detail, - metadata: metadata?.compactMapValues { String(describing: $0 )} + metadata: metadata?.asMetadata ) } } diff --git a/Sources/Decorator/Extensions+HKCategoryType.swift b/Sources/Decorator/Extensions+HKCategoryType.swift index 967282a..770ad1e 100644 --- a/Sources/Decorator/Extensions+HKCategoryType.swift +++ b/Sources/Decorator/Extensions+HKCategoryType.swift @@ -5,7 +5,6 @@ // Created by Victor Kachalov on 27.01.21. // -import Foundation import HealthKit extension HKCategoryType { diff --git a/Sources/Decorator/Extensions+HKCategoryValue.swift b/Sources/Decorator/Extensions+HKCategoryValue.swift index 12a7da5..f6a83f5 100644 --- a/Sources/Decorator/Extensions+HKCategoryValue.swift +++ b/Sources/Decorator/Extensions+HKCategoryValue.swift @@ -5,10 +5,9 @@ // Created by Kachalov, Victor on 05.09.21. // -import Foundation import HealthKit -extension HKCategoryValue: CustomStringConvertible { +extension HKCategoryValue: @retroactive CustomStringConvertible { public var description: String { "HKCategoryValue" } diff --git a/Sources/Decorator/Extensions+HKCategoryValueAppetiteChanges.swift b/Sources/Decorator/Extensions+HKCategoryValueAppetiteChanges.swift index d3a5402..51f8e26 100644 --- a/Sources/Decorator/Extensions+HKCategoryValueAppetiteChanges.swift +++ b/Sources/Decorator/Extensions+HKCategoryValueAppetiteChanges.swift @@ -5,11 +5,10 @@ // Created by Kachalov, Victor on 05.09.21. // -import Foundation import HealthKit @available(iOS 13.6, *) -extension HKCategoryValueAppetiteChanges: CustomStringConvertible { +extension HKCategoryValueAppetiteChanges: @retroactive CustomStringConvertible { public var description: String { "HKCategoryValueAppetiteChanges" } diff --git a/Sources/Decorator/Extensions+HKCategoryValueAppleStandHour.swift b/Sources/Decorator/Extensions+HKCategoryValueAppleStandHour.swift index caade38..ddab7d8 100644 --- a/Sources/Decorator/Extensions+HKCategoryValueAppleStandHour.swift +++ b/Sources/Decorator/Extensions+HKCategoryValueAppleStandHour.swift @@ -5,10 +5,9 @@ // Created by Kachalov, Victor on 05.09.21. // -import Foundation import HealthKit -extension HKCategoryValueAppleStandHour: CustomStringConvertible { +extension HKCategoryValueAppleStandHour: @retroactive CustomStringConvertible { public var description: String { "HKCategoryValueAppleStandHour" } diff --git a/Sources/Decorator/Extensions+HKCategoryValueAppleWalkingSteadinessEvent.swift b/Sources/Decorator/Extensions+HKCategoryValueAppleWalkingSteadinessEvent.swift new file mode 100644 index 0000000..aaecac4 --- /dev/null +++ b/Sources/Decorator/Extensions+HKCategoryValueAppleWalkingSteadinessEvent.swift @@ -0,0 +1,29 @@ +// +// Extensions+HKCategoryValueAppleWalkingSteadinessEvent.swift +// HealthKitReporter +// +// Created by Victor Kachalov on 04.10.22. +// + +import HealthKit + +@available(iOS 15.0, *) +extension HKCategoryValueAppleWalkingSteadinessEvent: @retroactive CustomStringConvertible { + public var description: String { + "HKCategoryValueAppleWalkingSteadinessEvent" + } + public var detail: String { + switch self { + case .initialLow: + return "Initial low" + case .initialVeryLow: + return "Initial very low" + case .repeatLow: + return "Repeat low" + case .repeatVeryLow: + return "Repeat very low" + @unknown default: + return "Unknown" + } + } +} diff --git a/Sources/Decorator/Extensions+HKCategoryValueAudioExposureEvent.swift b/Sources/Decorator/Extensions+HKCategoryValueAudioExposureEvent.swift index ee7b262..079fa35 100644 --- a/Sources/Decorator/Extensions+HKCategoryValueAudioExposureEvent.swift +++ b/Sources/Decorator/Extensions+HKCategoryValueAudioExposureEvent.swift @@ -5,11 +5,10 @@ // Created by Kachalov, Victor on 05.09.21. // -import Foundation import HealthKit @available(iOS 13.0, *) -extension HKCategoryValueAudioExposureEvent: CustomStringConvertible { +extension HKCategoryValueAudioExposureEvent: @retroactive CustomStringConvertible { public var description: String { "HKCategoryValueAudioExposureEvent" } diff --git a/Sources/Decorator/Extensions+HKCategoryValueCervicalMucusQuality.swift b/Sources/Decorator/Extensions+HKCategoryValueCervicalMucusQuality.swift index 152dc4e..8e08318 100644 --- a/Sources/Decorator/Extensions+HKCategoryValueCervicalMucusQuality.swift +++ b/Sources/Decorator/Extensions+HKCategoryValueCervicalMucusQuality.swift @@ -5,10 +5,9 @@ // Created by Kachalov, Victor on 05.09.21. // -import Foundation import HealthKit -extension HKCategoryValueCervicalMucusQuality: CustomStringConvertible { +extension HKCategoryValueCervicalMucusQuality: @retroactive CustomStringConvertible { public var description: String { "HKCategoryValueCervicalMucusQuality" } diff --git a/Sources/Decorator/Extensions+HKCategoryValueContraceptive.swift b/Sources/Decorator/Extensions+HKCategoryValueContraceptive.swift index c28120e..7a1d5fc 100644 --- a/Sources/Decorator/Extensions+HKCategoryValueContraceptive.swift +++ b/Sources/Decorator/Extensions+HKCategoryValueContraceptive.swift @@ -5,11 +5,10 @@ // Created by Kachalov, Victor on 05.09.21. // -import Foundation import HealthKit @available(iOS 14.3, *) -extension HKCategoryValueContraceptive: CustomStringConvertible { +extension HKCategoryValueContraceptive: @retroactive CustomStringConvertible { public var description: String { "HKCategoryValueContraceptive" } diff --git a/Sources/Decorator/Extensions+HKCategoryValueEnvironmentalAudioExposureEvent.swift b/Sources/Decorator/Extensions+HKCategoryValueEnvironmentalAudioExposureEvent.swift index 99c36c1..0d2d870 100644 --- a/Sources/Decorator/Extensions+HKCategoryValueEnvironmentalAudioExposureEvent.swift +++ b/Sources/Decorator/Extensions+HKCategoryValueEnvironmentalAudioExposureEvent.swift @@ -5,11 +5,10 @@ // Created by Kachalov, Victor on 05.09.21. // -import Foundation import HealthKit @available(iOS 14.0, *) -extension HKCategoryValueEnvironmentalAudioExposureEvent: CustomStringConvertible { +extension HKCategoryValueEnvironmentalAudioExposureEvent: @retroactive CustomStringConvertible { public var description: String { "HKCategoryValueEnvironmentalAudioExposureEvent" } diff --git a/Sources/Decorator/Extensions+HKCategoryValueHeadphoneAudioExposureEvent.swift b/Sources/Decorator/Extensions+HKCategoryValueHeadphoneAudioExposureEvent.swift index 971cfd1..5389088 100644 --- a/Sources/Decorator/Extensions+HKCategoryValueHeadphoneAudioExposureEvent.swift +++ b/Sources/Decorator/Extensions+HKCategoryValueHeadphoneAudioExposureEvent.swift @@ -5,11 +5,10 @@ // Created by Kachalov, Victor on 05.09.21. // -import Foundation import HealthKit @available(iOS 14.2, *) -extension HKCategoryValueHeadphoneAudioExposureEvent: CustomStringConvertible { +extension HKCategoryValueHeadphoneAudioExposureEvent: @retroactive CustomStringConvertible { public var description: String { "HKCategoryValueHeadphoneAudioExposureEvent" } diff --git a/Sources/Decorator/Extensions+HKCategoryValueLowCardioFitnessEvent.swift b/Sources/Decorator/Extensions+HKCategoryValueLowCardioFitnessEvent.swift index a92b95e..66292c2 100644 --- a/Sources/Decorator/Extensions+HKCategoryValueLowCardioFitnessEvent.swift +++ b/Sources/Decorator/Extensions+HKCategoryValueLowCardioFitnessEvent.swift @@ -5,11 +5,10 @@ // Created by Kachalov, Victor on 05.09.21. // -import Foundation import HealthKit @available(iOS 14.3, *) -extension HKCategoryValueLowCardioFitnessEvent: CustomStringConvertible { +extension HKCategoryValueLowCardioFitnessEvent: @retroactive CustomStringConvertible { public var description: String { String(describing: self) } diff --git a/Sources/Decorator/Extensions+HKCategoryValueMenstrualFlow.swift b/Sources/Decorator/Extensions+HKCategoryValueMenstrualFlow.swift index 1906629..796cfe3 100644 --- a/Sources/Decorator/Extensions+HKCategoryValueMenstrualFlow.swift +++ b/Sources/Decorator/Extensions+HKCategoryValueMenstrualFlow.swift @@ -5,10 +5,9 @@ // Created by Kachalov, Victor on 05.09.21. // -import Foundation import HealthKit -extension HKCategoryValueMenstrualFlow: CustomStringConvertible { +extension HKCategoryValueMenstrualFlow: @retroactive CustomStringConvertible { public var description: String { "HKCategoryValueMenstrualFlow" } diff --git a/Sources/Decorator/Extensions+HKCategoryValueOvulationTestResult.swift b/Sources/Decorator/Extensions+HKCategoryValueOvulationTestResult.swift index 3310800..8ae67d7 100644 --- a/Sources/Decorator/Extensions+HKCategoryValueOvulationTestResult.swift +++ b/Sources/Decorator/Extensions+HKCategoryValueOvulationTestResult.swift @@ -5,10 +5,9 @@ // Created by Kachalov, Victor on 05.09.21. // -import Foundation import HealthKit -extension HKCategoryValueOvulationTestResult: CustomStringConvertible { +extension HKCategoryValueOvulationTestResult: @retroactive CustomStringConvertible { public var description: String { "HKCategoryValueOvulationTestResult" } diff --git a/Sources/Decorator/Extensions+HKCategoryValuePregnancyTestResult.swift b/Sources/Decorator/Extensions+HKCategoryValuePregnancyTestResult.swift new file mode 100644 index 0000000..100677e --- /dev/null +++ b/Sources/Decorator/Extensions+HKCategoryValuePregnancyTestResult.swift @@ -0,0 +1,27 @@ +// +// Extensions+HKCategoryValuePregnancyTestResult.swift +// HealthKitReporter +// +// Created by Victor Kachalov on 04.10.22. +// + +import HealthKit + +@available(iOS 15.0, *) +extension HKCategoryValuePregnancyTestResult: @retroactive CustomStringConvertible { + public var description: String { + "HKCategoryValuePregnancyTestResult" + } + public var detail: String { + switch self { + case .negative: + return "Negative" + case .positive: + return "Positive" + case .indeterminate: + return "Indeterminate" + @unknown default: + return "Unknown" + } + } +} diff --git a/Sources/Decorator/Extensions+HKCategoryValuePresence.swift b/Sources/Decorator/Extensions+HKCategoryValuePresence.swift index 67e4c23..5d65e06 100644 --- a/Sources/Decorator/Extensions+HKCategoryValuePresence.swift +++ b/Sources/Decorator/Extensions+HKCategoryValuePresence.swift @@ -5,11 +5,10 @@ // Created by Kachalov, Victor on 05.09.21. // -import Foundation import HealthKit @available(iOS 13.6, *) -extension HKCategoryValuePresence: CustomStringConvertible { +extension HKCategoryValuePresence: @retroactive CustomStringConvertible { public var description: String { String(describing: self) } diff --git a/Sources/Decorator/Extensions+HKCategoryValueProgesteroneTestResult.swift b/Sources/Decorator/Extensions+HKCategoryValueProgesteroneTestResult.swift new file mode 100644 index 0000000..8123d35 --- /dev/null +++ b/Sources/Decorator/Extensions+HKCategoryValueProgesteroneTestResult.swift @@ -0,0 +1,27 @@ +// +// Extensions+HKCategoryValueProgesteroneTestResult.swift +// HealthKitReporter +// +// Created by Victor Kachalov on 04.10.22. +// + +import HealthKit + +@available(iOS 15.0, *) +extension HKCategoryValueProgesteroneTestResult: @retroactive CustomStringConvertible { + public var description: String { + "HKCategoryValueProgesteroneTestResult" + } + public var detail: String { + switch self { + case .negative: + return "Negative" + case .positive: + return "Positive" + case .indeterminate: + return "Indeterminate" + @unknown default: + return "Unknown" + } + } +} diff --git a/Sources/Decorator/Extensions+HKCategoryValueSeverity.swift b/Sources/Decorator/Extensions+HKCategoryValueSeverity.swift index 5e043eb..609acd6 100644 --- a/Sources/Decorator/Extensions+HKCategoryValueSeverity.swift +++ b/Sources/Decorator/Extensions+HKCategoryValueSeverity.swift @@ -5,11 +5,10 @@ // Created by Kachalov, Victor on 05.09.21. // -import Foundation import HealthKit @available(iOS 13.6, *) -extension HKCategoryValueSeverity: CustomStringConvertible { +extension HKCategoryValueSeverity: @retroactive CustomStringConvertible { public var description: String { "HKCategoryValueSeverity" } diff --git a/Sources/Decorator/Extensions+HKCategoryValueSleepAnalysis.swift b/Sources/Decorator/Extensions+HKCategoryValueSleepAnalysis.swift index ba4d897..de88170 100644 --- a/Sources/Decorator/Extensions+HKCategoryValueSleepAnalysis.swift +++ b/Sources/Decorator/Extensions+HKCategoryValueSleepAnalysis.swift @@ -5,10 +5,9 @@ // Created by Kachalov, Victor on 05.09.21. // -import Foundation import HealthKit -extension HKCategoryValueSleepAnalysis: CustomStringConvertible { +extension HKCategoryValueSleepAnalysis: @retroactive CustomStringConvertible { public var description: String { "HKCategoryValueSleepAnalysis" } @@ -16,10 +15,16 @@ extension HKCategoryValueSleepAnalysis: CustomStringConvertible { switch self { case .inBed: return "In Bed" - case .asleep: - return "Asleep" + case .asleepUnspecified: + return "Asleep unspecified" case .awake: return "Awake" + case .asleepCore: + return "Asleep core" + case .asleepDeep: + return "Asleep deep" + case .asleepREM: + return "Asleep REM" @unknown default: return "Unknown" } diff --git a/Sources/Decorator/Extensions+HKClinicalRecord.swift b/Sources/Decorator/Extensions+HKClinicalRecord.swift new file mode 100644 index 0000000..e6deef7 --- /dev/null +++ b/Sources/Decorator/Extensions+HKClinicalRecord.swift @@ -0,0 +1,36 @@ +// +// Extensions+HKClinicalRecord.swift +// HealthKitReporter +// +// Created by Quentin on 01.08.24. +// + +import HealthKit + +@available(iOS 12.0, *) +extension HKClinicalRecord: Harmonizable { + typealias Harmonized = ClinicalRecord.Harmonized + + func harmonize() throws -> Harmonized { + let fhirVersion: String? = if #available(iOS 14.0, *) { + fhirResource?.fhirVersion.stringRepresentation + } else { + nil + } + var fhirData: String? { + guard let data: Data = fhirResource?.data, + let jsonString = String(data: data, encoding: .utf8) else { + return nil + } + return jsonString + } + + return Harmonized( + displayName: displayName, + fhirSourceUrl: fhirResource?.sourceURL?.absoluteString, + fhirVersion: fhirVersion, + fhirData: fhirData, + metadata: metadata?.asMetadata + ) + } +} diff --git a/Sources/Decorator/Extensions+HKCorrelation.swift b/Sources/Decorator/Extensions+HKCorrelation.swift index 8ae173f..ea64b8f 100644 --- a/Sources/Decorator/Extensions+HKCorrelation.swift +++ b/Sources/Decorator/Extensions+HKCorrelation.swift @@ -5,7 +5,6 @@ // Created by Victor on 25.09.20. // -import Foundation import HealthKit extension HKCorrelation: Harmonizable { @@ -29,7 +28,7 @@ extension HKCorrelation: Harmonizable { return Harmonized( quantitySamples: quantityArray, categorySamples: categoryArray, - metadata: metadata?.compactMapValues { String(describing: $0 )} + metadata: metadata?.asMetadata ) } } diff --git a/Sources/Decorator/Extensions+HKElectrocardiogram.swift b/Sources/Decorator/Extensions+HKElectrocardiogram.swift index 17581b6..aa4f379 100644 --- a/Sources/Decorator/Extensions+HKElectrocardiogram.swift +++ b/Sources/Decorator/Extensions+HKElectrocardiogram.swift @@ -5,22 +5,15 @@ // Created by Victor on 24.09.20. // -import Foundation import HealthKit @available(iOS 14.0, *) -extension HKElectrocardiogram: Harmonizable { +extension HKElectrocardiogram { typealias Harmonized = Electrocardiogram.Harmonized - func harmonize() throws -> Harmonized { + func harmonize(voltageMeasurements: [Electrocardiogram.VoltageMeasurement]) throws -> Harmonized { let averageHeartRateUnit = HKUnit.count().unitDivided(by: HKUnit.minute()) - guard - let averageHeartRate = averageHeartRate?.doubleValue(for: averageHeartRateUnit) - else { - throw HealthKitError.invalidValue( - "Invalid averageHeartRate value for HKElectrocardiogram" - ) - } + let averageHeartRate = averageHeartRate?.doubleValue(for: averageHeartRateUnit) let samplingFrequencyUnit = HKUnit.hertz() guard let samplingFrequency = samplingFrequency?.doubleValue(for: samplingFrequencyUnit) @@ -29,16 +22,16 @@ extension HKElectrocardiogram: Harmonizable { "Invalid samplingFrequency value for HKElectrocardiogram" ) } - let classification = String(describing: self.classification) - let symptomsStatus = String(describing: self.symptomsStatus) return Harmonized( averageHeartRate: averageHeartRate, averageHeartRateUnit: averageHeartRateUnit.unitString, samplingFrequency: samplingFrequency, samplingFrequencyUnit: samplingFrequencyUnit.unitString, - classification: classification, - symptomsStatus: symptomsStatus, - metadata: metadata?.compactMapValues { String(describing: $0 )} + classification: classification.description, + symptomsStatus: symptomsStatus.description, + count: numberOfVoltageMeasurements, + voltageMeasurements: voltageMeasurements, + metadata: metadata?.asMetadata ) } } @@ -60,3 +53,45 @@ extension HKElectrocardiogram.VoltageMeasurement: Harmonizable { return Harmonized(value: voltage, unit: unit.unitString) } } +// MARK: - CustomStringConvertible +@available(iOS 14.0, *) +extension HKElectrocardiogram.Classification: @retroactive CustomStringConvertible { + public var description: String { + switch self { + case .notSet: + return "na" + case .sinusRhythm: + return "Sinus rhytm" + case .atrialFibrillation: + return "Atrial fibrillation" + case .inconclusiveLowHeartRate: + return "Inconclusive low heart rate" + case .inconclusiveHighHeartRate: + return "Inconclusive high heart rate" + case .inconclusivePoorReading: + return "Inconclusive poor reading" + case .inconclusiveOther: + return "Inconclusive other" + case .unrecognized: + return "Unrecognized" + @unknown default: + fatalError() + } + } +} +// MARK: - CustomStringConvertible +@available(iOS 14.0, *) +extension HKElectrocardiogram.SymptomsStatus: @retroactive CustomStringConvertible { + public var description: String { + switch self { + case .notSet: + return "na" + case .none: + return "None" + case .present: + return "Present" + @unknown default: + fatalError() + } + } +} diff --git a/Sources/Decorator/Extensions+HKFitzpatrickSkinType.swift b/Sources/Decorator/Extensions+HKFitzpatrickSkinType.swift index 5b2ae4b..38c5bea 100644 --- a/Sources/Decorator/Extensions+HKFitzpatrickSkinType.swift +++ b/Sources/Decorator/Extensions+HKFitzpatrickSkinType.swift @@ -5,10 +5,9 @@ // Created by Victor on 15.09.20. // -import Foundation import HealthKit -extension HKFitzpatrickSkinType: CustomStringConvertible { +extension HKFitzpatrickSkinType: @retroactive CustomStringConvertible { public var description: String { switch self { case .notSet: diff --git a/Sources/Decorator/Extensions+HKHeartbeatSeriesSample.swift b/Sources/Decorator/Extensions+HKHeartbeatSeriesSample.swift index 22ace76..7c807b9 100644 --- a/Sources/Decorator/Extensions+HKHeartbeatSeriesSample.swift +++ b/Sources/Decorator/Extensions+HKHeartbeatSeriesSample.swift @@ -5,7 +5,6 @@ // Created by Kachalov, Victor on 12.10.21. // -import Foundation import HealthKit @available(iOS 13.0, *) @@ -16,7 +15,7 @@ extension HKHeartbeatSeriesSample { Harmonized( count: count, measurements: measurements, - metadata: metadata?.compactMapValues { String(describing: $0) } + metadata: metadata?.asMetadata ) } } diff --git a/Sources/Decorator/Extensions+HKQuantitiySample.swift b/Sources/Decorator/Extensions+HKQuantitiySample.swift index 1d04599..dbe5232 100644 --- a/Sources/Decorator/Extensions+HKQuantitiySample.swift +++ b/Sources/Decorator/Extensions+HKQuantitiySample.swift @@ -5,7 +5,6 @@ // Created by Victor on 15.09.20. // -import Foundation import HealthKit // SI parsing @@ -23,7 +22,8 @@ extension HKQuantitySample: Harmonizable { .swimmingStrokeCount, .numberOfTimesFallen, .inhalerUsage, - .uvExposure: + .uvExposure, + .numberOfAlcoholicBeverages: return quantity(unit: HKUnit.count()) case .distanceCycling, .distanceSwimming, @@ -33,12 +33,16 @@ extension HKQuantitySample: Harmonizable { .height, .waistCircumference, .walkingStepLength, - .sixMinuteWalkTestDistance: + .sixMinuteWalkTestDistance, + .runningStrideLength, + .runningVerticalOscillation, + .underwaterDepth: return quantity(unit: HKUnit.meter()) case .heartRate, .respiratoryRate, .restingHeartRate, - .walkingHeartRateAverage: + .walkingHeartRateAverage, + .heartRateRecoveryOneMinute: return quantity(unit: HKUnit.count().unitDivided(by: HKUnit.minute())) case .basalEnergyBurned, .activeEnergyBurned, @@ -49,14 +53,18 @@ extension HKQuantitySample: Harmonizable { return quantity(unit: HKUnit.kilocalorie()) } case .basalBodyTemperature, - .bodyTemperature: + .bodyTemperature, + .appleSleepingWristTemperature, + .waterTemperature: return quantity(unit: HKUnit.kelvin()) case .oxygenSaturation, .bodyFatPercentage, .walkingDoubleSupportPercentage, .walkingAsymmetryPercentage, .peripheralPerfusionIndex, - .bloodAlcoholContent: + .bloodAlcoholContent, + .appleWalkingSteadiness, + .atrialFibrillationBurden: return quantity(unit: HKUnit.percent()) case .bloodPressureSystolic, .bloodPressureDiastolic: @@ -108,7 +116,9 @@ extension HKQuantitySample: Harmonizable { .leanBodyMass: return quantity(unit: HKUnit.gramUnit(with: .kilo)) case .appleExerciseTime, - .appleStandTime: + .appleStandTime, + .appleMoveTime, + .runningGroundContactTime: return quantity(unit: HKUnit.second()) case .vo2Max: return quantity( @@ -116,7 +126,8 @@ extension HKQuantitySample: Harmonizable { ) case .walkingSpeed, .stairAscentSpeed, - .stairDescentSpeed: + .stairDescentSpeed, + .runningSpeed: return quantity(unit: HKUnit.meter().unitDivided(by: HKUnit.second())) case .heartRateVariabilitySDNN: return quantity(unit: HKUnit.secondUnit(with: .milli)) @@ -136,6 +147,14 @@ extension HKQuantitySample: Harmonizable { case .environmentalAudioExposure, .headphoneAudioExposure: return quantity(unit: HKUnit.pascal()) + case .runningPower: + if #available(iOS 16.0, *) { + return quantity(unit: HKUnit.watt()) + } else { + throw HealthKitError.notAvailable( + "\(type) is not available for the current iOS" + ) + } } } @@ -144,7 +163,7 @@ extension HKQuantitySample: Harmonizable { return Harmonized( value: value, unit: unit.unitString, - metadata: metadata?.compactMapValues { String(describing: $0) } + metadata: metadata?.asMetadata ) } } diff --git a/Sources/Decorator/Extensions+HKQuantityType.swift b/Sources/Decorator/Extensions+HKQuantityType.swift index 4f76ec5..6285d06 100644 --- a/Sources/Decorator/Extensions+HKQuantityType.swift +++ b/Sources/Decorator/Extensions+HKQuantityType.swift @@ -5,7 +5,6 @@ // Created by Victor on 15.09.20. // -import Foundation import HealthKit extension HKQuantityType { diff --git a/Sources/Decorator/Extensions+HKSample.swift b/Sources/Decorator/Extensions+HKSample.swift index a8ef243..04ad2ee 100644 --- a/Sources/Decorator/Extensions+HKSample.swift +++ b/Sources/Decorator/Extensions+HKSample.swift @@ -5,7 +5,6 @@ // Created by Victor on 25.09.20. // -import Foundation import HealthKit extension HKSample { @@ -24,7 +23,12 @@ extension HKSample { } if #available(iOS 14.0, *) { if let electrocardiogram = self as? HKElectrocardiogram { - return try Electrocardiogram(electrocardiogram: electrocardiogram) + return try Electrocardiogram(electrocardiogram: electrocardiogram, voltageMeasurements: []) + } + } + if #available(iOS 12.0, *) { + if let clinicalRecord = self as? HKClinicalRecord { + return try ClinicalRecord(clinicalRecord: clinicalRecord) } } throw HealthKitError.parsingFailed("HKSample could not be parsed") diff --git a/Sources/Decorator/Extensions+HKSourceRevision.swift b/Sources/Decorator/Extensions+HKSourceRevision.swift index b33a4cf..6d6a5db 100644 --- a/Sources/Decorator/Extensions+HKSourceRevision.swift +++ b/Sources/Decorator/Extensions+HKSourceRevision.swift @@ -5,7 +5,6 @@ // Created by Victor on 24.09.20. // -import Foundation import HealthKit extension HKSourceRevision { diff --git a/Sources/Decorator/Extensions+HKStatistics.swift b/Sources/Decorator/Extensions+HKStatistics.swift index efa1222..6482abe 100644 --- a/Sources/Decorator/Extensions+HKStatistics.swift +++ b/Sources/Decorator/Extensions+HKStatistics.swift @@ -5,7 +5,6 @@ // Created by Victor on 15.09.20. // -import Foundation import HealthKit // SI parsing @@ -23,7 +22,8 @@ extension HKStatistics: Harmonizable { .swimmingStrokeCount, .numberOfTimesFallen, .inhalerUsage, - .uvExposure: + .uvExposure, + .numberOfAlcoholicBeverages: return statistics(unit: HKUnit.count()) case .distanceCycling, .distanceSwimming, @@ -33,12 +33,16 @@ extension HKStatistics: Harmonizable { .height, .waistCircumference, .walkingStepLength, - .sixMinuteWalkTestDistance: + .sixMinuteWalkTestDistance, + .runningStrideLength, + .runningVerticalOscillation, + .underwaterDepth: return statistics(unit: HKUnit.meter()) case .heartRate, .respiratoryRate, .restingHeartRate, - .walkingHeartRateAverage: + .walkingHeartRateAverage, + .heartRateRecoveryOneMinute: return statistics(unit: HKUnit.count().unitDivided(by: HKUnit.minute())) case .basalEnergyBurned, .activeEnergyBurned, @@ -49,14 +53,18 @@ extension HKStatistics: Harmonizable { return statistics(unit: HKUnit.kilocalorie()) } case .basalBodyTemperature, - .bodyTemperature: + .bodyTemperature, + .appleSleepingWristTemperature, + .waterTemperature: return statistics(unit: HKUnit.kelvin()) case .oxygenSaturation, .bodyFatPercentage, .walkingDoubleSupportPercentage, .walkingAsymmetryPercentage, .peripheralPerfusionIndex, - .bloodAlcoholContent: + .bloodAlcoholContent, + .appleWalkingSteadiness, + .atrialFibrillationBurden: return statistics(unit: HKUnit.percent()) case .bloodPressureSystolic, .bloodPressureDiastolic: @@ -108,7 +116,9 @@ extension HKStatistics: Harmonizable { .leanBodyMass: return statistics(unit: HKUnit.gramUnit(with: .kilo)) case .appleExerciseTime, - .appleStandTime: + .appleStandTime, + .appleMoveTime, + .runningGroundContactTime: return statistics(unit: HKUnit.second()) case .vo2Max: return statistics( @@ -116,7 +126,8 @@ extension HKStatistics: Harmonizable { ) case .walkingSpeed, .stairAscentSpeed, - .stairDescentSpeed: + .stairDescentSpeed, + .runningSpeed: return statistics(unit: HKUnit.meter().unitDivided(by: HKUnit.second())) case .heartRateVariabilitySDNN: return statistics(unit: HKUnit.secondUnit(with: .milli)) @@ -136,6 +147,14 @@ extension HKStatistics: Harmonizable { case .environmentalAudioExposure, .headphoneAudioExposure: return statistics(unit: HKUnit.pascal()) + case .runningPower: + if #available(iOS 16.0, *) { + return statistics(unit: HKUnit.watt()) + } else { + throw HealthKitError.notAvailable( + "\(type) is not available for the current iOS" + ) + } } } diff --git a/Sources/Decorator/Extensions+HKVisionPrescription.swift b/Sources/Decorator/Extensions+HKVisionPrescription.swift new file mode 100644 index 0000000..7b74b31 --- /dev/null +++ b/Sources/Decorator/Extensions+HKVisionPrescription.swift @@ -0,0 +1,22 @@ +// +// Extensions+HKVisionPrescription.swift +// HealthKitReporter +// +// Created by Victor Kachalov on 04.10.22. +// + +import HealthKit + +@available(iOS 16.0, *) +extension HKVisionPrescription: Harmonizable { + typealias Harmonized = VisionPrescription.Harmonized + + func harmonize() throws -> Harmonized { + return Harmonized( + dateIssuedTimestamp: dateIssued.millisecondsSince1970, + expirationDateTimestamp: expirationDate?.millisecondsSince1970, + prescriptionType: VisionPrescription.PrescriptionType(prescriptionType: prescriptionType), + metadata: metadata?.asMetadata + ) + } +} diff --git a/Sources/Decorator/Extensions+HKVisionPrescriptionType.swift b/Sources/Decorator/Extensions+HKVisionPrescriptionType.swift new file mode 100644 index 0000000..cabf523 --- /dev/null +++ b/Sources/Decorator/Extensions+HKVisionPrescriptionType.swift @@ -0,0 +1,25 @@ +// +// Extensions+HKVisionPrescriptionType.swift +// HealthKitReporter +// +// Created by Victor Kachalov on 04.10.22. +// + +import HealthKit + +@available(iOS 16.0, *) +extension HKVisionPrescriptionType: @retroactive CustomStringConvertible { + public var description: String { + "HKVisionPrescriptionType" + } + public var detail: String { + switch self { + case .glasses: + return "Glasses" + case .contacts: + return "Contacts" + @unknown default: + return "Unknown" + } + } +} diff --git a/Sources/Decorator/Extensions+HKWheelchairUse.swift b/Sources/Decorator/Extensions+HKWheelchairUse.swift index 0cf9111..6616d64 100644 --- a/Sources/Decorator/Extensions+HKWheelchairUse.swift +++ b/Sources/Decorator/Extensions+HKWheelchairUse.swift @@ -5,7 +5,6 @@ // Created by Victor Kachalov on 27.01.21. // -import Foundation import HealthKit @available(iOS 10.0, *) diff --git a/Sources/Decorator/Extensions+HKWorkout.swift b/Sources/Decorator/Extensions+HKWorkout.swift index af8035b..6444ee8 100644 --- a/Sources/Decorator/Extensions+HKWorkout.swift +++ b/Sources/Decorator/Extensions+HKWorkout.swift @@ -5,7 +5,6 @@ // Created by Victor on 25.09.20. // -import Foundation import HealthKit extension HKWorkout: Harmonizable { @@ -43,7 +42,7 @@ extension HKWorkout: Harmonizable { totalSwimmingStrokeCountUnit: countUnit.unitString, totalFlightsClimbed: totalFlightsClimbed, totalFlightsClimbedUnit: countUnit.unitString, - metadata: metadata?.compactMapValues { String(describing: $0 )} + metadata: metadata?.asMetadata ) } } diff --git a/Sources/Decorator/Extensions+HKWorkoutActivityType.swift b/Sources/Decorator/Extensions+HKWorkoutActivityType.swift index 2f949b2..fe91d3d 100644 --- a/Sources/Decorator/Extensions+HKWorkoutActivityType.swift +++ b/Sources/Decorator/Extensions+HKWorkoutActivityType.swift @@ -5,10 +5,9 @@ // Created by Oliver Searle-Barnes on 01.04.21. // -import Foundation import HealthKit -extension HKWorkoutActivityType: CustomStringConvertible { +extension HKWorkoutActivityType: @retroactive CustomStringConvertible { public var description: String { switch self { case .americanFootball: @@ -171,8 +170,14 @@ extension HKWorkoutActivityType: CustomStringConvertible { return "Pickerball" case .cooldown: return "Cooldown" + case .swimBikeRun: + return "Swim Bike Run" + case .transition: + return "Transition" case .other: return "Other" + case .underwaterDiving: + return "Underwater Diving" @unknown default: return "Unknown Workout" } } diff --git a/Sources/Decorator/Extensions+HKWorkoutConfiguration.swift b/Sources/Decorator/Extensions+HKWorkoutConfiguration.swift index e850df4..6dc4be7 100644 --- a/Sources/Decorator/Extensions+HKWorkoutConfiguration.swift +++ b/Sources/Decorator/Extensions+HKWorkoutConfiguration.swift @@ -5,7 +5,6 @@ // Created by Victor on 25.09.20. // -import Foundation import HealthKit @available(iOS 10.0, *) diff --git a/Sources/Decorator/Extensions+HKWorkoutEvent.swift b/Sources/Decorator/Extensions+HKWorkoutEvent.swift index 0f48a93..1bc4fca 100644 --- a/Sources/Decorator/Extensions+HKWorkoutEvent.swift +++ b/Sources/Decorator/Extensions+HKWorkoutEvent.swift @@ -5,7 +5,6 @@ // Created by Victor on 25.09.20. // -import Foundation import HealthKit extension HKWorkoutEvent: Harmonizable { @@ -16,7 +15,8 @@ extension HKWorkoutEvent: Harmonizable { return Harmonized( value: type.rawValue, description: type.description, - metadata: metadata?.compactMapValues { String(describing: $0 )}) + metadata: metadata?.asMetadata + ) } else { throw HealthKitError.notAvailable( "Metadata is not available for the current iOS" diff --git a/Sources/Decorator/Extensions+HKWorkoutEventType.swift b/Sources/Decorator/Extensions+HKWorkoutEventType.swift index 034636c..e7a5a5d 100644 --- a/Sources/Decorator/Extensions+HKWorkoutEventType.swift +++ b/Sources/Decorator/Extensions+HKWorkoutEventType.swift @@ -5,10 +5,9 @@ // Created by Kachalov, Victor on 04.09.21. // -import Foundation import HealthKit -extension HKWorkoutEventType: CustomStringConvertible { +extension HKWorkoutEventType: @retroactive CustomStringConvertible { public var description: String { switch self { case .pause: diff --git a/Sources/Decorator/Extensions+HKWorkoutRoute.swift b/Sources/Decorator/Extensions+HKWorkoutRoute.swift new file mode 100644 index 0000000..f88011e --- /dev/null +++ b/Sources/Decorator/Extensions+HKWorkoutRoute.swift @@ -0,0 +1,21 @@ +// +// Extensions+HKWorkoutRoute.swift +// HealthKitReporter +// +// Created by Victor Kachalov on 16.04.22. +// + +import HealthKit + +@available(iOS 11.0, *) +extension HKWorkoutRoute { + typealias Harmonized = WorkoutRoute.Harmonized + + func harmonize(routes: [WorkoutRoute.Route]) -> Harmonized { + Harmonized( + count: count, + routes: routes, + metadata: metadata?.asMetadata + ) + } +} diff --git a/Sources/Decorator/Extensions+NSPredicate.swift b/Sources/Decorator/Extensions+NSPredicate.swift index 3a5ae65..4c21dd2 100644 --- a/Sources/Decorator/Extensions+NSPredicate.swift +++ b/Sources/Decorator/Extensions+NSPredicate.swift @@ -5,7 +5,6 @@ // Created by Victor on 14.09.20. // -import Foundation import HealthKit public extension NSPredicate { diff --git a/Sources/Decorator/Extensions+String.swift b/Sources/Decorator/Extensions+String.swift index fd93063..58f9ab2 100644 --- a/Sources/Decorator/Extensions+String.swift +++ b/Sources/Decorator/Extensions+String.swift @@ -47,6 +47,11 @@ public extension String { return type } } + if #available(iOS 12.0, *) { + if let type = try? ClinicalType.make(from: self) { + return type + } + } return nil } diff --git a/Sources/HealthKitReporter.swift b/Sources/HealthKitReporter.swift index df663bb..6ce53a2 100644 --- a/Sources/HealthKitReporter.swift +++ b/Sources/HealthKitReporter.swift @@ -5,7 +5,6 @@ // Created by Victor on 23.09.20. // -import Foundation import HealthKit /// ***HKQueryAnchor** typealias @@ -92,11 +91,12 @@ public typealias HeartbeatSeriesResultsDataHandler = ( ) -> Void /** - Parameters: - - workoutRoute: workout route. + - routes: workout routes. - error: error (optional) */ -public typealias WorkoutRouteDataHandler = ( - _ workoutRoute: WorkoutRoute?, +@available(iOS 11.0, *) +public typealias WorkoutRouteResultsDataHandler = ( + _ routes: [WorkoutRoute], _ error: Error? ) -> Void /** @@ -183,12 +183,12 @@ public typealias PreferredUnitsCompeltion = ( ) -> Void /** - Parameters: - - samples: electrocardiogram sample array. Empty by default + - ecgs: electrocardiogram sample array - error: error (optional) */ @available(iOS 14.0, *) public typealias ElectrocardiogramResultsHandler = ( - _ samples: [Electrocardiogram], + _ ecgs: [Electrocardiogram], _ error: Error? ) -> Void /** @@ -196,12 +196,6 @@ public typealias ElectrocardiogramResultsHandler = ( - samples: electrocardiogram voltage measurements sample array. Empty by default - error: error (optional) */ -@available(iOS 14.0, *) -public typealias ElectrocardiogramVoltageMeasurementDataHandler = ( - _ measurement: Electrocardiogram.VoltageMeasurement?, - _ done: Bool, - _ error: Error? -) -> Void /// **HealthKitReporter** class for HK easy integration public class HealthKitReporter { @@ -213,17 +207,21 @@ public class HealthKitReporter { public let observer: HealthKitObserver /// **HealthKitManager** is reponsible for authorization and other operations public let manager: HealthKitManager + /** + Checks if HealthData is available on the device (for instance iPad do not support Apple Health). + Call this check before instantiating the **HealthKitReporter** instance + - Returns: **Bool** value + */ + public static var isHealthDataAvailable: Bool { + HKHealthStore.isHealthDataAvailable() + } /** Inits the instance of **HealthKitReporter** class. Every time when called, the new instance of **HKHealthStore** is created. - Requires: Apple Healt App is installed on the device. - - Throws: `HealthKitError.notAvailable` - Returns: **HealthKitReporter** instance */ - public init() throws { - guard HKHealthStore.isHealthDataAvailable() else { - throw HealthKitError.notAvailable() - } + public init() { let healthStore = HKHealthStore() self.reader = HealthKitReader(healthStore: healthStore) self.writer = HealthKitWriter(healthStore: healthStore) diff --git a/Sources/Model/Metadata.swift b/Sources/Model/Metadata.swift new file mode 100644 index 0000000..55fefe0 --- /dev/null +++ b/Sources/Model/Metadata.swift @@ -0,0 +1,57 @@ +// +// Metadata.swift +// HealthKitReporter +// +// Created by Victor Kachalov on 29.10.22. +// + +import Foundation + +public enum Metadata: Codable { + case string(dictionary: [String: String]?) + case date(dictionary: [String: Date]?) + case double(dictionary: [String: Double]?) + + public var original: [String: Any]? { + switch self { + case .string(dictionary: let dictionary): + return dictionary + case .date(dictionary: let dictionary): + return dictionary + case .double(dictionary: let dictionary): + return dictionary + } + } +} +// MARK: - Metadata: ExpressibleByDictionaryLiteral, Equatable +extension Metadata: ExpressibleByDictionaryLiteral, Equatable { + public typealias Key = String + public typealias Value = Any + + public init(dictionaryLiteral elements: (Key, Value)...) { + var dictionary = [String: Any]() + for pair in elements { + dictionary[pair.0] = pair.1 + } + do { + self = try Metadata.make(from: dictionary) + } catch { + self = [:] + } + } +} +// MARK: - Metadata: Payload +extension Metadata: Payload { + public static func make(from dictionary: [String : Any]) throws -> Metadata { + if let stringDictionary = dictionary as? [String: String] { + return Metadata.string(dictionary: stringDictionary) + } + if let dateDictionary = dictionary as? [String: Date] { + return Metadata.date(dictionary: dateDictionary) + } + if let doubleDictionary = dictionary as? [String: Double] { + return Metadata.double(dictionary: doubleDictionary) + } + throw HealthKitError.invalidValue("Invalid dictionary: \(dictionary)") + } +} diff --git a/Sources/Model/Payload/ActivitySummary.swift b/Sources/Model/Payload/ActivitySummary.swift index 69c7d56..f939884 100644 --- a/Sources/Model/Payload/ActivitySummary.swift +++ b/Sources/Model/Payload/ActivitySummary.swift @@ -5,7 +5,6 @@ // Created by Victor on 25.09.20. // -import Foundation import HealthKit @available(iOS 9.3, *) diff --git a/Sources/Model/Payload/Category.swift b/Sources/Model/Payload/Category.swift index cb43347..74957c1 100644 --- a/Sources/Model/Payload/Category.swift +++ b/Sources/Model/Payload/Category.swift @@ -5,7 +5,6 @@ // Created by Victor on 25.09.20. // -import Foundation import HealthKit public struct Category: Identifiable, Sample { @@ -13,13 +12,13 @@ public struct Category: Identifiable, Sample { public let value: Int public let description: String public let detail: String - public let metadata: [String: String]? + public let metadata: Metadata? public init( value: Int, description: String, detail: String, - metadata: [String: String]? + metadata: Metadata? ) { self.value = value self.description = description @@ -31,7 +30,7 @@ public struct Category: Identifiable, Sample { value: Int? = nil, description: String? = nil, detail: String? = nil, - metadata: [String: String]? = nil + metadata: Metadata? = nil ) -> Harmonized { return Harmonized( value: value ?? self.value, @@ -50,25 +49,6 @@ public struct Category: Identifiable, Sample { public let sourceRevision: SourceRevision public let harmonized: Harmonized - public static func collect( - results: [HKSample] - ) -> [Category] { - var samples = [Category]() - if let categorySamples = results as? [HKCategorySample] { - for categorySample in categorySamples { - do { - let sample = try Category( - categorySample: categorySample - ) - samples.append(sample) - } catch { - continue - } - } - } - return samples - } - init(categorySample: HKCategorySample) throws { self.uuid = categorySample.uuid.uuidString self.identifier = categorySample.categoryType.identifier @@ -128,15 +108,13 @@ extension Category: Original { start: startTimestamp.asDate, end: endTimestamp.asDate, device: device?.asOriginal(), - metadata: harmonized.metadata + metadata: harmonized.metadata?.original ) } } // MARK: - Payload extension Category: Payload { - public static func make( - from dictionary: [String : Any] - ) throws -> Category { + public static func make(from dictionary: [String: Any]) throws -> Category { guard let identifier = dictionary["identifier"] as? String, let startTimestamp = dictionary["startTimestamp"] as? NSNumber, @@ -149,8 +127,8 @@ extension Category: Payload { let device = dictionary["device"] as? [String: Any] return Category( identifier: identifier, - startTimestamp: Double(truncating: startTimestamp).secondsSince1970, - endTimestamp: Double(truncating: endTimestamp).secondsSince1970, + startTimestamp: Double(truncating: startTimestamp), + endTimestamp: Double(truncating: endTimestamp), device: device != nil ? try Device.make(from: device!) : nil, @@ -158,12 +136,39 @@ extension Category: Payload { harmonized: try Harmonized.make(from: harmonized) ) } + public static func collect(from array: [Any]) throws -> [Category] { + var results = [Category]() + for element in array { + if let dictionary = element as? [String: Any] { + let harmonized = try Category.make(from: dictionary) + results.append(harmonized) + } + } + return results + } +} +// MARK: - Factory +extension Category { + public static func collect(results: [HKSample]) -> [Category] { + var samples = [Category]() + if let categorySamples = results as? [HKCategorySample] { + for categorySample in categorySamples { + do { + let sample = try Category( + categorySample: categorySample + ) + samples.append(sample) + } catch { + continue + } + } + } + return samples + } } // MARK: - Payload extension Category.Harmonized: Payload { - public static func make( - from dictionary: [String : Any] - ) throws -> Category.Harmonized { + public static func make(from dictionary: [String: Any]) throws -> Category.Harmonized { guard let value = dictionary["value"] as? Int, let description = dictionary["description"] as? String, @@ -171,12 +176,12 @@ extension Category.Harmonized: Payload { else { throw HealthKitError.invalidValue("Invalid dictionary: \(dictionary)") } - let metadata = dictionary["metadata"] as? [String: String] + let metadata = dictionary["metadata"] as? [String: Any] return Category.Harmonized( value: value, description: description, detail: detail, - metadata: metadata + metadata: metadata?.asMetadata ) } } diff --git a/Sources/Model/Payload/Characteristic.swift b/Sources/Model/Payload/Characteristic.swift index 3310632..e6d5e8e 100644 --- a/Sources/Model/Payload/Characteristic.swift +++ b/Sources/Model/Payload/Characteristic.swift @@ -5,7 +5,6 @@ // Created by Victor on 25.09.20. // -import Foundation import HealthKit public struct Characteristic: Codable { diff --git a/Sources/Model/Payload/ClinicalRecord.swift b/Sources/Model/Payload/ClinicalRecord.swift new file mode 100644 index 0000000..78ee9e6 --- /dev/null +++ b/Sources/Model/Payload/ClinicalRecord.swift @@ -0,0 +1,199 @@ +// +// ClinicalRecord.swift +// HealthKitReporter +// +// Created by Quentin on 01.08.24. +// + +import HealthKit + +@available(iOS 12.0, *) +public struct ClinicalRecord: Identifiable, Sample { + public struct Harmonized: Codable { + public let displayName: String + public let fhirSourceUrl: String? + public let fhirVersion: String? + public let fhirData: String? + public let metadata: Metadata? + + public init( + displayName: String, + fhirSourceUrl: String?, + fhirVersion: String?, + fhirData: String?, + metadata: Metadata? + ) { + self.displayName = displayName + self.fhirSourceUrl = fhirSourceUrl + self.fhirVersion = fhirVersion + self.fhirData = fhirData + self.metadata = metadata + } + + public func copyWith( + displayName: String? = nil, + fhirSourceUrl: String? = nil, + fhirVersion: String? = nil, + fhirData: String? = nil, + metadata: Metadata? = nil + ) -> Harmonized { + return Harmonized( + displayName: displayName ?? self.displayName, + fhirSourceUrl: fhirSourceUrl ?? self.fhirSourceUrl, + fhirVersion: fhirVersion ?? self.fhirVersion, + fhirData: fhirData ?? self.fhirData, + metadata: metadata ?? self.metadata + ) + } + } + + public let uuid: String + public let identifier: String + public let startTimestamp: Double + public let endTimestamp: Double + public let device: Device? + public let sourceRevision: SourceRevision + public let harmonized: Harmonized + + init(clinicalRecord: HKClinicalRecord) throws { + let fhirVersion: String? = if #available(iOS 14.0, *) { + clinicalRecord.fhirResource?.fhirVersion.stringRepresentation + } else { + nil + } + var fhirData: String? { + guard let data: Data = clinicalRecord.fhirResource?.data, + let jsonString = String(data: data, encoding: .utf8) else { + return nil + } + return jsonString + } + + self.uuid = clinicalRecord.uuid.uuidString + self.identifier = clinicalRecord.clinicalType.identifier + self.startTimestamp = clinicalRecord.startDate.timeIntervalSince1970 + self.endTimestamp = clinicalRecord.endDate.timeIntervalSince1970 + self.device = Device(device: clinicalRecord.device) + self.sourceRevision = SourceRevision(sourceRevision: clinicalRecord.sourceRevision) + self.harmonized = Harmonized( + displayName: clinicalRecord.displayName, + fhirSourceUrl: clinicalRecord.fhirResource?.sourceURL?.absoluteString, + fhirVersion: fhirVersion, + fhirData: fhirData, + metadata: clinicalRecord.metadata?.asMetadata + ) + } + + public init( + identifier: String, + startTimestamp: Double, + endTimestamp: Double, + device: Device?, + sourceRevision: SourceRevision, + harmonized: Harmonized + ) { + self.uuid = UUID().uuidString + self.identifier = identifier + self.startTimestamp = startTimestamp + self.endTimestamp = endTimestamp + self.device = device + self.sourceRevision = sourceRevision + self.harmonized = harmonized + } + + public func copyWith( + identifier: String? = nil, + startTimestamp: Double? = nil, + endTimestamp: Double? = nil, + device: Device? = nil, + sourceRevision: SourceRevision? = nil, + harmonized: Harmonized? = nil + ) -> ClinicalRecord { + return ClinicalRecord( + identifier: identifier ?? self.identifier, + startTimestamp: startTimestamp ?? self.startTimestamp, + endTimestamp: endTimestamp ?? self.endTimestamp, + device: device ?? self.device, + sourceRevision: sourceRevision ?? self.sourceRevision, + harmonized: harmonized ?? self.harmonized + ) + } +} +// MARK: - Payload +@available(iOS 12.0, *) +extension ClinicalRecord: Payload { + public static func make(from dictionary: [String: Any]) throws -> ClinicalRecord { + guard + let identifier = dictionary["identifier"] as? String, + let startTimestamp = dictionary["startTimestamp"] as? NSNumber, + let endTimestamp = dictionary["endTimestamp"] as? NSNumber, + let sourceRevision = dictionary["sourceRevision"] as? [String: Any], + let harmonized = dictionary["harmonized"] as? [String: Any] + else { + throw HealthKitError.invalidValue("Invalid dictionary: \(dictionary)") + } + let device = dictionary["device"] as? [String: Any] + return ClinicalRecord( + identifier: identifier, + startTimestamp: Double(truncating: startTimestamp), + endTimestamp: Double(truncating: endTimestamp), + device: device != nil + ? try Device.make(from: device!) + : nil, + sourceRevision: try SourceRevision.make(from: sourceRevision), + harmonized: try Harmonized.make(from: harmonized) + ) + } + public static func collect(from array: [Any]) throws -> [ClinicalRecord] { + var results = [ClinicalRecord]() + for element in array { + if let dictionary = element as? [String: Any] { + let harmonized = try ClinicalRecord.make(from: dictionary) + results.append(harmonized) + } + } + return results + } +} +// MARK: - Factory +@available(iOS 12.0, *) +extension ClinicalRecord { + public static func collect(results: [HKSample]) -> [ClinicalRecord] { + var samples = [ClinicalRecord]() + if let clinicalRecords = results as? [HKClinicalRecord] { + for clinicalRecord in clinicalRecords { + do { + let sample = try ClinicalRecord( + clinicalRecord: clinicalRecord + ) + samples.append(sample) + } catch { + continue + } + } + } + return samples + } +} +// MARK: - Payload +@available(iOS 12.0, *) +extension ClinicalRecord.Harmonized: Payload { + public static func make(from dictionary: [String: Any]) throws -> ClinicalRecord.Harmonized { + guard + let displayName = dictionary["displayName"] as? String, + let fhirSourceUrl = dictionary["fhirSourceUrl"] as? String?, + let fhirVersion = dictionary["fhirVersion"] as? String?, + let fhirData = dictionary["fhirData"] as? String? + else { + throw HealthKitError.invalidValue("Invalid dictionary: \(dictionary)") + } + let metadata = dictionary["metadata"] as? [String: Any] + return ClinicalRecord.Harmonized( + displayName: displayName, + fhirSourceUrl: fhirSourceUrl, + fhirVersion: fhirVersion, + fhirData: fhirData, + metadata: metadata?.asMetadata + ) + } +} diff --git a/Sources/Model/Payload/Correlation.swift b/Sources/Model/Payload/Correlation.swift index 4838691..4e40e8e 100644 --- a/Sources/Model/Payload/Correlation.swift +++ b/Sources/Model/Payload/Correlation.swift @@ -5,24 +5,35 @@ // Created by Victor on 25.09.20. // -import Foundation import HealthKit public struct Correlation: Identifiable, Sample { public struct Harmonized: Codable { public let quantitySamples: [Quantity] public let categorySamples: [Category] - public let metadata: [String: String]? + public let metadata: Metadata? public init( quantitySamples: [Quantity], categorySamples: [Category], - metadata: [String: String]? + metadata: Metadata? ) { self.quantitySamples = quantitySamples self.categorySamples = categorySamples self.metadata = metadata } + + public func copyWith( + quantitySamples: [Quantity]? = nil, + categorySamples: [Category]? = nil, + metadata: Metadata? = nil + ) -> Correlation.Harmonized { + return Correlation.Harmonized( + quantitySamples: quantitySamples ?? self.quantitySamples, + categorySamples: categorySamples ?? self.categorySamples, + metadata: metadata ?? self.metadata + ) + } } public let uuid: String @@ -33,6 +44,55 @@ public struct Correlation: Identifiable, Sample { public let sourceRevision: SourceRevision public let harmonized: Harmonized + init(correlation: HKCorrelation) throws { + self.sourceRevision = SourceRevision( + sourceRevision: correlation.sourceRevision + ) + self.uuid = correlation.uuid.uuidString + self.identifier = correlation.correlationType.identifier + self.startTimestamp = correlation.startDate.timeIntervalSince1970 + self.endTimestamp = correlation.endDate.timeIntervalSince1970 + self.device = Device(device: correlation.device) + self.harmonized = try correlation.harmonize() + } + + public init( + identifier: String, + startTimestamp: Double, + endTimestamp: Double, + device: Device?, + sourceRevision: SourceRevision, + harmonized: Correlation.Harmonized + ) { + self.uuid = UUID().uuidString + self.identifier = identifier + self.startTimestamp = startTimestamp + self.endTimestamp = endTimestamp + self.device = device + self.sourceRevision = sourceRevision + self.harmonized = harmonized + } + + public func copyWith( + identifier: String? = nil, + startTimestamp: Double? = nil, + endTimestamp: Double? = nil, + device: Device? = nil, + sourceRevision: SourceRevision? = nil, + harmonized: Harmonized? = nil + ) -> Correlation { + return Correlation( + identifier: identifier ?? self.identifier, + startTimestamp: startTimestamp ?? self.startTimestamp, + endTimestamp: endTimestamp ?? self.endTimestamp, + device: device ?? self.device, + sourceRevision: sourceRevision ?? self.sourceRevision, + harmonized: harmonized ?? self.harmonized + ) + } +} +// MARK: - Factory +extension Correlation { public static func collect( results: [HKSample] ) -> [Correlation] { @@ -51,17 +111,48 @@ public struct Correlation: Identifiable, Sample { } return samples } +} +// MARK: - Payload +extension Correlation: Payload { + public static func make(from dictionary: [String: Any]) throws -> Correlation { + guard + let identifier = dictionary["identifier"] as? String, + let startTimestamp = dictionary["startTimestamp"] as? NSNumber, + let endTimestamp = dictionary["endTimestamp"] as? NSNumber, + let sourceRevision = dictionary["sourceRevision"] as? [String: Any], + let harmonized = dictionary["harmonized"] as? [String: Any] + else { + throw HealthKitError.invalidValue("Invalid dictionary: \(dictionary)") + } + let device = dictionary["device"] as? [String: Any] + return Correlation( + identifier: identifier, + startTimestamp: Double(truncating: startTimestamp), + endTimestamp: Double(truncating: endTimestamp), + device: device != nil + ? try Device.make(from: device!) + : nil, + sourceRevision: try SourceRevision.make(from: sourceRevision), + harmonized: try Correlation.Harmonized.make(from: harmonized) + ) + } +} +// MARK: - Payload +extension Correlation.Harmonized: Payload { + public static func make(from dictionary: [String: Any]) throws -> Correlation.Harmonized { + guard + let quantitySamples = dictionary["quantitySamples"] as? [Any], + let categorySamples = dictionary["categorySamples"] as? [Any] + else { + throw HealthKitError.invalidValue("Invalid dictionary: \(dictionary)") + } + let metadata = dictionary["metadata"] as? [String: Any] - init(correlation: HKCorrelation) throws { - self.sourceRevision = SourceRevision( - sourceRevision: correlation.sourceRevision + return Correlation.Harmonized( + quantitySamples: try Quantity.collect(from: quantitySamples), + categorySamples: try Category.collect(from: categorySamples), + metadata: metadata?.asMetadata ) - self.uuid = correlation.uuid.uuidString - self.identifier = correlation.correlationType.identifier - self.startTimestamp = correlation.startDate.timeIntervalSince1970 - self.endTimestamp = correlation.endDate.timeIntervalSince1970 - self.device = Device(device: correlation.device) - self.harmonized = try correlation.harmonize() } } // MARK: - Original @@ -79,8 +170,8 @@ extension Correlation: Original { } } for element in harmonized.quantitySamples { - if let category = try? element.asOriginal() { - set.insert(category) + if let quantity = try? element.asOriginal() { + set.insert(quantity) } } return HKCorrelation( @@ -89,7 +180,7 @@ extension Correlation: Original { end: endTimestamp.asDate, objects: set, device: device?.asOriginal(), - metadata: harmonized.metadata + metadata: harmonized.metadata?.original ) } } diff --git a/Sources/Model/Payload/DeletedObject.swift b/Sources/Model/Payload/DeletedObject.swift index ea35f85..c45b382 100644 --- a/Sources/Model/Payload/DeletedObject.swift +++ b/Sources/Model/Payload/DeletedObject.swift @@ -5,22 +5,23 @@ // Created by Kachalov, Victor on 16.02.21. // -import Foundation import HealthKit public struct DeletedObject: Codable { public let uuid: String - public let metadata: [String: String]? + public let metadata: Metadata? init(deletedObject: HKDeletedObject) { self.uuid = deletedObject.uuid.uuidString if #available(iOS 11.0, *) { - self.metadata = deletedObject.metadata?.compactMapValues { String(describing: $0 )} + self.metadata = deletedObject.metadata?.asMetadata } else { self.metadata = nil } } - +} +// MARK: - Factory +extension DeletedObject { public static func collect( deletedObjects: [HKDeletedObject]? ) -> [DeletedObject] { diff --git a/Sources/Model/Payload/Device.swift b/Sources/Model/Payload/Device.swift index ced3e9a..7f339fb 100644 --- a/Sources/Model/Payload/Device.swift +++ b/Sources/Model/Payload/Device.swift @@ -5,7 +5,6 @@ // Created by Victor on 25.09.20. // -import Foundation import HealthKit public struct Device: Codable { diff --git a/Sources/Model/Payload/Electrocardiogram.swift b/Sources/Model/Payload/Electrocardiogram.swift index 11a83d3..1c26cbe 100644 --- a/Sources/Model/Payload/Electrocardiogram.swift +++ b/Sources/Model/Payload/Electrocardiogram.swift @@ -5,28 +5,31 @@ // Created by Victor on 25.09.20. // -import Foundation import HealthKit @available(iOS 14.0, *) public struct Electrocardiogram: Identifiable, Sample { public struct Harmonized: Codable { - public let averageHeartRate: Double + public let averageHeartRate: Double? public let averageHeartRateUnit: String public let samplingFrequency: Double public let samplingFrequencyUnit: String public let classification: String public let symptomsStatus: String - public let metadata: [String: String]? + public let count: Int + public let voltageMeasurements: [VoltageMeasurement] + public let metadata: Metadata? - public init( - averageHeartRate: Double, + init( + averageHeartRate: Double?, averageHeartRateUnit: String, samplingFrequency: Double, samplingFrequencyUnit: String, classification: String, symptomsStatus: String, - metadata: [String: String]? + count: Int, + voltageMeasurements: [VoltageMeasurement], + metadata: Metadata? ) { self.averageHeartRate = averageHeartRate self.averageHeartRateUnit = averageHeartRateUnit @@ -34,6 +37,8 @@ public struct Electrocardiogram: Identifiable, Sample { self.samplingFrequencyUnit = samplingFrequencyUnit self.classification = classification self.symptomsStatus = symptomsStatus + self.count = count + self.voltageMeasurements = voltageMeasurements self.metadata = metadata } } @@ -46,6 +51,11 @@ public struct Electrocardiogram: Identifiable, Sample { public let harmonized: Harmonized public let timeSinceSampleStart: Double + init(harmonized: Harmonized, timeSinceSampleStart: Double) { + self.harmonized = harmonized + self.timeSinceSampleStart = timeSinceSampleStart + } + init(voltageMeasurement: HKElectrocardiogram.VoltageMeasurement) throws { self.harmonized = try voltageMeasurement.harmonize() self.timeSinceSampleStart = voltageMeasurement.timeSinceSampleStart @@ -61,15 +71,87 @@ public struct Electrocardiogram: Identifiable, Sample { public let numberOfMeasurements: Int public let harmonized: Harmonized - public static func collect( - results: [HKSample] - ) -> [Electrocardiogram] { + init( + identifier: String, + startTimestamp: Double, + endTimestamp: Double, + device: Device?, + sourceRevision: SourceRevision, + numberOfMeasurements: Int, + harmonized: Harmonized + ) { + self.uuid = UUID().uuidString + self.identifier = identifier + self.startTimestamp = startTimestamp + self.endTimestamp = endTimestamp + self.device = device + self.sourceRevision = sourceRevision + self.numberOfMeasurements = numberOfMeasurements + self.harmonized = harmonized + } + + init( + electrocardiogram: HKElectrocardiogram, + voltageMeasurements: [Electrocardiogram.VoltageMeasurement] + ) throws { + self.uuid = electrocardiogram.uuid.uuidString + self.identifier = ElectrocardiogramType + .electrocardiogramType + .original? + .identifier ?? "HKDataTypeIdentifierElectrocardiogram" + self.startTimestamp = electrocardiogram.startDate.timeIntervalSince1970 + self.endTimestamp = electrocardiogram.endDate.timeIntervalSince1970 + self.device = Device(device: electrocardiogram.device) + self.numberOfMeasurements = electrocardiogram.numberOfVoltageMeasurements + self.sourceRevision = SourceRevision(sourceRevision: electrocardiogram.sourceRevision) + self.harmonized = try electrocardiogram.harmonize(voltageMeasurements: voltageMeasurements) + } +} +// MARK: - Payload +@available(iOS 14.0, *) +extension Electrocardiogram.Harmonized: Payload { + public static func make(from dictionary: [String: Any]) throws -> Electrocardiogram.Harmonized { + guard + let averageHeartRateUnit = dictionary["averageHeartRateUnit"] as? String, + let samplingFrequency = dictionary["samplingFrequency"] as? NSNumber, + let samplingFrequencyUnit = dictionary["samplingFrequencyUnit"] as? String, + let classification = dictionary["classification"] as? String, + let symptomsStatus = dictionary["symptomsStatus"] as? String, + let count = dictionary["count"] as? Int + else { + throw HealthKitError.invalidValue("Invalid dictionary: \(dictionary)") + } + let averageHeartRate = dictionary["averageHeartRate"] as? NSNumber + let voltageMeasurements = dictionary["voltageMeasurements"] as? [Any] + let metadata = dictionary["metadata"] as? [String: Any] + return Electrocardiogram.Harmonized( + averageHeartRate: averageHeartRate != nil + ? Double(truncating: averageHeartRate!) + : nil, + averageHeartRateUnit: averageHeartRateUnit, + samplingFrequency: Double(truncating: samplingFrequency), + samplingFrequencyUnit: samplingFrequencyUnit, + classification: classification, + symptomsStatus: symptomsStatus, + count: count, + voltageMeasurements: voltageMeasurements != nil + ? try Electrocardiogram.VoltageMeasurement.collect(from: voltageMeasurements!) + : [], + metadata: metadata?.asMetadata + ) + } +} +// MARK: - Factory +@available(iOS 14.0, *) +extension Electrocardiogram { + static func collect(results: [HKSample]) -> [Electrocardiogram] { var samples = [Electrocardiogram]() if let electrocardiograms = results as? [HKElectrocardiogram] { for electrocardiogram in electrocardiograms { do { let sample = try Electrocardiogram( - electrocardiogram: electrocardiogram + electrocardiogram: electrocardiogram, + voltageMeasurements: [] ) samples.append(sample) } catch { @@ -79,18 +161,76 @@ public struct Electrocardiogram: Identifiable, Sample { } return samples } - - init(electrocardiogram: HKElectrocardiogram) throws { - self.uuid = electrocardiogram.uuid.uuidString - self.identifier = ElectrocardiogramType - .electrocardiogramType - .original? - .identifier ?? "HKElectrocardiogram" - self.startTimestamp = electrocardiogram.startDate.timeIntervalSince1970 - self.endTimestamp = electrocardiogram.endDate.timeIntervalSince1970 - self.device = Device(device: electrocardiogram.device) - self.numberOfMeasurements = electrocardiogram.numberOfVoltageMeasurements - self.sourceRevision = SourceRevision(sourceRevision: electrocardiogram.sourceRevision) - self.harmonized = try electrocardiogram.harmonize() +} +// MARK: - Payload +@available(iOS 14.0, *) +extension Electrocardiogram: Payload { + public static func make(from dictionary: [String: Any]) throws -> Electrocardiogram { + guard + let identifier = dictionary["identifier"] as? String, + let startTimestamp = dictionary["startTimestamp"] as? NSNumber, + let endTimestamp = dictionary["endTimestamp"] as? NSNumber, + let sourceRevision = dictionary["sourceRevision"] as? [String: Any], + let numberOfMeasurements = dictionary["numberOfMeasurements"] as? Int, + let harmonized = dictionary["harmonized"] as? [String: Any] + else { + throw HealthKitError.invalidValue("Invalid dictionary: \(dictionary)") + } + let device = dictionary["device"] as? [String: Any] + return Electrocardiogram( + identifier: identifier, + startTimestamp: Double(truncating: startTimestamp), + endTimestamp: Double(truncating: endTimestamp), + device: device != nil + ? try Device.make(from: device!) + : nil, + sourceRevision: try SourceRevision.make(from: sourceRevision), + numberOfMeasurements: numberOfMeasurements, + harmonized: try Harmonized.make(from: harmonized) + ) + } +} +// MARK: - Payload +@available(iOS 14.0, *) +extension Electrocardiogram.VoltageMeasurement: Payload { + public static func make(from dictionary: [String: Any]) throws -> Electrocardiogram.VoltageMeasurement { + guard + let harmonized = dictionary["harmonized"] as? [String: Any], + let timeSinceSampleStart = dictionary["timeSinceSampleStart"] as? NSNumber + else { + throw HealthKitError.invalidValue("Invalid dictionary: \(dictionary)") + } + return Electrocardiogram.VoltageMeasurement( + harmonized: try Electrocardiogram.VoltageMeasurement.Harmonized.make(from: harmonized), + timeSinceSampleStart: Double(truncating: timeSinceSampleStart) + ) + } + static func collect(from array: [Any]) throws -> [Electrocardiogram.VoltageMeasurement] { + var measurements = [Electrocardiogram.VoltageMeasurement]() + for element in array { + if let dictionary = element as? [String: Any] { + let measurement = try Electrocardiogram.VoltageMeasurement.make(from: dictionary) + measurements.append(measurement) + } + } + return measurements + } +} +// MARK: - Payload +@available(iOS 14.0, *) +extension Electrocardiogram.VoltageMeasurement.Harmonized: Payload { + public static func make( + from dictionary: [String: Any] + ) throws -> Electrocardiogram.VoltageMeasurement.Harmonized { + guard + let value = dictionary["value"] as? NSNumber, + let unit = dictionary["unit"] as? String + else { + throw HealthKitError.invalidValue("Invalid dictionary: \(dictionary)") + } + return Electrocardiogram.VoltageMeasurement.Harmonized( + value: Double(truncating: value), + unit: unit + ) } } diff --git a/Sources/Model/Payload/HeartbeatSeries.swift b/Sources/Model/Payload/HeartbeatSeries.swift index 4847841..8c196d0 100644 --- a/Sources/Model/Payload/HeartbeatSeries.swift +++ b/Sources/Model/Payload/HeartbeatSeries.swift @@ -5,7 +5,6 @@ // Created by Kachalov, Victor on 12.10.21. // -import Foundation import HealthKit @available(iOS 13.0, *) @@ -14,6 +13,7 @@ public struct HeartbeatSeries: Identifiable, Sample { public let timeSinceSeriesStart: Double public let precededByGap: Bool public let done: Bool + public init( timeSinceSeriesStart: Double, precededByGap: Bool, @@ -28,12 +28,12 @@ public struct HeartbeatSeries: Identifiable, Sample { public struct Harmonized: Codable { public let count: Int public let measurements: [Measurement] - public let metadata: [String: String]? + public let metadata: Metadata? public init( count: Int, measurements: [Measurement], - metadata: [String: String]? + metadata: Metadata? ) { self.count = count self.measurements = measurements @@ -43,7 +43,7 @@ public struct HeartbeatSeries: Identifiable, Sample { public func copyWith( count: Int? = nil, measurements: [Measurement]? = nil, - metadata: [String: String]? = nil + metadata: Metadata? = nil ) -> Harmonized { return Harmonized( count: count ?? self.count, @@ -77,6 +77,7 @@ public struct HeartbeatSeries: Identifiable, Sample { self.sourceRevision = sourceRevision self.harmonized = harmonized } + init(sample: HKHeartbeatSeriesSample, measurements: [Measurement]) { self.uuid = sample.uuid.uuidString self.identifier = sample.sampleType.identifier @@ -87,3 +88,75 @@ public struct HeartbeatSeries: Identifiable, Sample { self.harmonized = sample.harmonize(measurements: measurements) } } +// MARK: - Payload +@available(iOS 13.0, *) +extension HeartbeatSeries: Payload { + public static func make(from dictionary: [String: Any]) throws -> HeartbeatSeries { + guard + let identifier = dictionary["identifier"] as? String, + let startTimestamp = dictionary["startTimestamp"] as? NSNumber, + let endTimestamp = dictionary["endTimestamp"] as? NSNumber, + let sourceRevision = dictionary["sourceRevision"] as? [String: Any], + let harmonized = dictionary["harmonized"] as? [String: Any] + else { + throw HealthKitError.invalidValue("Invalid dictionary: \(dictionary)") + } + let device = dictionary["device"] as? [String: Any] + return HeartbeatSeries( + identifier: identifier, + startTimestamp: Double(truncating: startTimestamp), + endTimestamp: Double(truncating: endTimestamp), + device: device != nil + ? try Device.make(from: device!) + : nil, + sourceRevision: try SourceRevision.make(from: sourceRevision), + harmonized: try Harmonized.make(from: harmonized) + ) + } +} +// MARK: - Payload +@available(iOS 13.0, *) +extension HeartbeatSeries.Harmonized: Payload { + public static func make(from dictionary: [String: Any]) throws -> HeartbeatSeries.Harmonized { + guard + let count = dictionary["count"] as? Int, + let measurements = dictionary["measurements"] as? [Any] + else { + throw HealthKitError.invalidValue("Invalid dictionary: \(dictionary)") + } + let metadata = dictionary["metadata"] as? [String: Any] + return HeartbeatSeries.Harmonized( + count: count, + measurements: try HeartbeatSeries.Measurement.collect(from: measurements), + metadata: metadata?.asMetadata + ) + } +} +// MARK: - Payload +@available(iOS 13.0, *) +extension HeartbeatSeries.Measurement: Payload { + public static func make(from dictionary: [String: Any]) throws -> HeartbeatSeries.Measurement { + guard + let timeSinceSeriesStart = dictionary["timeSinceSeriesStart"] as? NSNumber, + let precededByGap = dictionary["precededByGap"] as? Bool, + let done = dictionary["done"] as? Bool + else { + throw HealthKitError.invalidValue("Invalid dictionary: \(dictionary)") + } + return HeartbeatSeries.Measurement( + timeSinceSeriesStart: Double(truncating: timeSinceSeriesStart), + precededByGap: precededByGap, + done: done + ) + } + public static func collect(from array: [Any]) throws -> [HeartbeatSeries.Measurement] { + var measurements = [HeartbeatSeries.Measurement]() + for element in array { + if let dictionary = element as? [String: Any] { + let measurement = try HeartbeatSeries.Measurement.make(from: dictionary) + measurements.append(measurement) + } + } + return measurements + } +} diff --git a/Sources/Model/Payload/Quantity.swift b/Sources/Model/Payload/Quantity.swift index cafdf7b..db831d4 100644 --- a/Sources/Model/Payload/Quantity.swift +++ b/Sources/Model/Payload/Quantity.swift @@ -5,19 +5,18 @@ // Created by Victor on 25.09.20. // -import Foundation import HealthKit public struct Quantity: Identifiable, Sample { public struct Harmonized: Codable { public let value: Double public let unit: String - public let metadata: [String: String]? + public let metadata: Metadata? public init( value: Double, unit: String, - metadata: [String: String]? + metadata: Metadata? ) { self.value = value self.unit = unit @@ -27,7 +26,7 @@ public struct Quantity: Identifiable, Sample { public func copyWith( value: Double? = nil, unit: String? = nil, - metadata: [String: String]? = nil + metadata: Metadata? = nil ) -> Harmonized { return Harmonized( value: value ?? self.value, @@ -45,27 +44,6 @@ public struct Quantity: Identifiable, Sample { public let sourceRevision: SourceRevision public let harmonized: Harmonized - public static func collect( - results: [HKSample], - unit: HKUnit - ) -> [Quantity] { - var samples = [Quantity]() - if let quantitySamples = results as? [HKQuantitySample] { - for quantitySample in quantitySamples { - do { - let sample = try Quantity( - quantitySample: quantitySample, - unit: unit - ) - samples.append(sample) - } catch { - continue - } - } - } - return samples - } - init(quantitySample: HKQuantitySample, unit: HKUnit) throws { self.uuid = quantitySample.uuid.uuidString self.identifier = quantitySample.quantityType.identifier @@ -76,7 +54,7 @@ public struct Quantity: Identifiable, Sample { self.harmonized = Harmonized( value: quantitySample.quantity.doubleValue(for: unit), unit: unit.unitString, - metadata: quantitySample.metadata?.compactMapValues { String(describing: $0 )} + metadata: quantitySample.metadata?.asMetadata ) } init(quantitySample: HKQuantitySample) throws { @@ -141,15 +119,13 @@ extension Quantity: Original { start: startTimestamp.asDate, end: endTimestamp.asDate, device: device?.asOriginal(), - metadata: harmonized.metadata + metadata: harmonized.metadata?.original ) } } // MARK: - Payload extension Quantity: Payload { - public static func make( - from dictionary: [String : Any] - ) throws -> Quantity { + public static func make(from dictionary: [String: Any]) throws -> Quantity { guard let identifier = dictionary["identifier"] as? String, let startTimestamp = dictionary["startTimestamp"] as? NSNumber, @@ -162,8 +138,8 @@ extension Quantity: Payload { let device = dictionary["device"] as? [String: Any] return Quantity( identifier: identifier, - startTimestamp: Double(truncating: startTimestamp).secondsSince1970, - endTimestamp: Double(truncating: endTimestamp).secondsSince1970, + startTimestamp: Double(truncating: startTimestamp), + endTimestamp: Double(truncating: endTimestamp), device: device != nil ? try Device.make(from: device!) : nil, @@ -171,23 +147,51 @@ extension Quantity: Payload { harmonized: try Harmonized.make(from: harmonized) ) } + public static func collect(from array: [Any]) throws -> [Quantity] { + var results = [Quantity]() + for element in array { + if let dictionary = element as? [String: Any] { + let harmonized = try Quantity.make(from: dictionary) + results.append(harmonized) + } + } + return results + } +} +// MARK: - Factory +extension Quantity { + public static func collect(results: [HKSample], unit: HKUnit) -> [Quantity] { + var samples = [Quantity]() + if let quantitySamples = results as? [HKQuantitySample] { + for quantitySample in quantitySamples { + do { + let sample = try Quantity( + quantitySample: quantitySample, + unit: unit + ) + samples.append(sample) + } catch { + continue + } + } + } + return samples + } } // MARK: - Payload extension Quantity.Harmonized: Payload { - public static func make( - from dictionary: [String : Any] - ) throws -> Quantity.Harmonized { + public static func make(from dictionary: [String: Any]) throws -> Quantity.Harmonized { guard let value = dictionary["value"] as? NSNumber, let unit = dictionary["unit"] as? String else { throw HealthKitError.invalidValue("Invalid dictionary: \(dictionary)") } - let metadata = dictionary["metadata"] as? [String: String] + let metadata = dictionary["metadata"] as? [String: Any] return Quantity.Harmonized( value: Double(truncating: value), unit: unit, - metadata: metadata + metadata: metadata?.asMetadata ) } } diff --git a/Sources/Model/Payload/Sample.swift b/Sources/Model/Payload/Sample.swift index cbee750..cd8760a 100644 --- a/Sources/Model/Payload/Sample.swift +++ b/Sources/Model/Payload/Sample.swift @@ -6,7 +6,6 @@ // import Foundation -import HealthKit public protocol Sample: Codable { var startTimestamp: Double { get } diff --git a/Sources/Model/Payload/Source.swift b/Sources/Model/Payload/Source.swift index 5c30423..1b9adfc 100644 --- a/Sources/Model/Payload/Source.swift +++ b/Sources/Model/Payload/Source.swift @@ -5,7 +5,6 @@ // Created by Victor on 25.09.20. // -import Foundation import HealthKit public struct Source: Codable { diff --git a/Sources/Model/Payload/SourceRevision.swift b/Sources/Model/Payload/SourceRevision.swift index d9b8a20..1edd4df 100644 --- a/Sources/Model/Payload/SourceRevision.swift +++ b/Sources/Model/Payload/SourceRevision.swift @@ -5,7 +5,6 @@ // Created by Victor on 25.09.20. // -import Foundation import HealthKit public struct SourceRevision: Codable { diff --git a/Sources/Model/Payload/Statistics.swift b/Sources/Model/Payload/Statistics.swift index 73683f1..67fbd1d 100644 --- a/Sources/Model/Payload/Statistics.swift +++ b/Sources/Model/Payload/Statistics.swift @@ -5,7 +5,6 @@ // Created by Victor on 25.09.20. // -import Foundation import HealthKit public struct Statistics: Identifiable, Sample { diff --git a/Sources/Model/Payload/VisionPrescription.swift b/Sources/Model/Payload/VisionPrescription.swift new file mode 100644 index 0000000..76e38d1 --- /dev/null +++ b/Sources/Model/Payload/VisionPrescription.swift @@ -0,0 +1,144 @@ +// +// VisionPrescription.swift +// HealthKitReporter +// +// Created by Victor Kachalov on 04.10.22. +// + +import HealthKit + +@available(iOS 16.0, *) +public struct VisionPrescription: Identifiable, Sample { + public struct PrescriptionType: Codable { + public let id: Int + public let detail: String + + init(id: Int, detail: String) { + self.id = id + self.detail = detail + } + + init(prescriptionType: HKVisionPrescriptionType) { + self.id = Int(prescriptionType.rawValue) + self.detail = prescriptionType.detail + } + } + + public struct Harmonized: Codable { + public let dateIssuedTimestamp: Double + public let expirationDateTimestamp: Double? + public let prescriptionType: PrescriptionType + public let metadata: Metadata? + + init( + dateIssuedTimestamp: Double, + expirationDateTimestamp: Double?, + prescriptionType: PrescriptionType, + metadata: Metadata? + ) { + self.dateIssuedTimestamp = dateIssuedTimestamp + self.expirationDateTimestamp = expirationDateTimestamp + self.prescriptionType = prescriptionType + self.metadata = metadata + } + } + + public let uuid: String + public let identifier: String + public let startTimestamp: Double + public let endTimestamp: Double + public let device: Device? + public let sourceRevision: SourceRevision + public let harmonized: Harmonized + + init( + identifier: String, + startTimestamp: Double, + endTimestamp: Double, + device: Device?, + sourceRevision: SourceRevision, + harmonized: Harmonized + ) { + self.uuid = UUID().uuidString + self.identifier = identifier + self.startTimestamp = startTimestamp + self.endTimestamp = endTimestamp + self.device = device + self.sourceRevision = sourceRevision + self.harmonized = harmonized + } + + init(visionPrescription: HKVisionPrescription) throws { + self.uuid = visionPrescription.uuid.uuidString + self.identifier = VisionPrescriptionType + .visionPrescription + .original? + .identifier ?? "HKVisionPrescriptionTypeIdentifier" + self.startTimestamp = visionPrescription.startDate.timeIntervalSince1970 + self.endTimestamp = visionPrescription.endDate.timeIntervalSince1970 + self.device = Device(device: visionPrescription.device) + self.sourceRevision = SourceRevision(sourceRevision: visionPrescription.sourceRevision) + self.harmonized = try visionPrescription.harmonize() + } +} +// MARK: - Payload +@available(iOS 16.0, *) +extension VisionPrescription.Harmonized: Payload { + public static func make(from dictionary: [String: Any]) throws -> VisionPrescription.Harmonized { + guard + let dateIssuedTimestamp = dictionary["dateIssuedTimestamp"] as? NSNumber, + let prescriptionType = dictionary["prescriptionType"] as? [String: Any] + else { + throw HealthKitError.invalidValue("Invalid dictionary: \(dictionary)") + } + let expirationDateTimestamp = dictionary["expirationDateTimestamp"] as? NSNumber + let metadata = dictionary["metadata"] as? [String: Any] + return VisionPrescription.Harmonized( + dateIssuedTimestamp: Double(truncating: dateIssuedTimestamp), + expirationDateTimestamp: expirationDateTimestamp != nil + ? Double(truncating: expirationDateTimestamp!) + : nil, + prescriptionType: try VisionPrescription.PrescriptionType.make(from: prescriptionType), + metadata: metadata?.asMetadata + ) + } +} +// MARK: - Payload +@available(iOS 16.0, *) +extension VisionPrescription.PrescriptionType: Payload { + public static func make(from dictionary: [String: Any]) throws -> VisionPrescription.PrescriptionType { + guard + let id = dictionary["id"] as? NSNumber, + let detail = dictionary["detail"] as? String + else { + throw HealthKitError.invalidValue("Invalid dictionary: \(dictionary)") + } + return VisionPrescription.PrescriptionType(id: id.intValue, detail: detail) + } +} +// MARK: - Payload +@available(iOS 16.0, *) +extension VisionPrescription: Payload { + public static func make(from dictionary: [String: Any]) throws -> VisionPrescription { + guard + let identifier = dictionary["identifier"] as? String, + let startTimestamp = dictionary["startTimestamp"] as? NSNumber, + let endTimestamp = dictionary["endTimestamp"] as? NSNumber, + let sourceRevision = dictionary["sourceRevision"] as? [String: Any], + let harmonized = dictionary["harmonized"] as? [String: Any] + else { + throw HealthKitError.invalidValue("Invalid dictionary: \(dictionary)") + } + let device = dictionary["device"] as? [String: Any] + return VisionPrescription( + identifier: identifier, + startTimestamp: Double(truncating: startTimestamp), + endTimestamp: Double(truncating: endTimestamp), + device: device != nil + ? try Device.make(from: device!) + : nil, + sourceRevision: try SourceRevision.make(from: sourceRevision), + harmonized: try Harmonized.make(from: harmonized) + ) + } +} diff --git a/Sources/Model/Payload/Workout.swift b/Sources/Model/Payload/Workout.swift index fb22868..8f862ca 100644 --- a/Sources/Model/Payload/Workout.swift +++ b/Sources/Model/Payload/Workout.swift @@ -5,7 +5,6 @@ // Created by Victor on 25.09.20. // -import Foundation import HealthKit public struct Workout: Identifiable, Sample { @@ -20,7 +19,7 @@ public struct Workout: Identifiable, Sample { public let totalSwimmingStrokeCountUnit: String public let totalFlightsClimbed: Double? public let totalFlightsClimbedUnit: String - public let metadata: [String: String]? + public let metadata: Metadata? public init( value: Int, @@ -33,7 +32,7 @@ public struct Workout: Identifiable, Sample { totalSwimmingStrokeCountUnit: String, totalFlightsClimbed: Double?, totalFlightsClimbedUnit: String, - metadata: [String: String]? + metadata: Metadata? ) { self.value = value self.description = description @@ -59,7 +58,7 @@ public struct Workout: Identifiable, Sample { totalSwimmingStrokeCountUnit: String? = nil, totalFlightsClimbed: Double? = nil, totalFlightsClimbedUnit: String? = nil, - metadata: [String: String]? = nil + metadata: Metadata? = nil ) -> Harmonized { return Harmonized( value: value ?? self.value, @@ -87,25 +86,6 @@ public struct Workout: Identifiable, Sample { public let workoutEvents: [WorkoutEvent] public let harmonized: Harmonized - public static func collect( - results: [HKSample] - ) -> [Workout] { - var samples = [Workout]() - if let workouts = results as? [HKWorkout] { - for workout in workouts { - do { - let sample = try Workout( - workout: workout - ) - samples.append(sample) - } catch { - continue - } - } - } - return samples - } - init(workout: HKWorkout) throws { self.uuid = workout.uuid.uuidString self.identifier = workout.sampleType.identifier @@ -194,7 +174,7 @@ extension Workout: Original { activityType: activityType, start: startTimestamp.asDate, end: endTimestamp.asDate, - workoutEvents: try workoutEvents.map({ try $0.asOriginal() }), + workoutEvents: try workoutEvents.map { try $0.asOriginal() }, totalEnergyBurned: harmonized.totalEnergyBurned != nil ? HKQuantity( unit: HKUnit.init(from: harmonized.totalEnergyBurnedUnit), @@ -214,7 +194,7 @@ extension Workout: Original { ) : nil, device: device?.asOriginal(), - metadata: harmonized.metadata + metadata: harmonized.metadata?.original ) } } @@ -237,8 +217,8 @@ extension Workout: Payload { let workoutEvents = dictionary["workoutEvents"] as? [[String: Any]] return Workout( identifier: identifier, - startTimestamp: Double(truncating: startTimestamp).secondsSince1970, - endTimestamp: Double(truncating: endTimestamp).secondsSince1970, + startTimestamp: Double(truncating: startTimestamp), + endTimestamp: Double(truncating: endTimestamp), device: device != nil ? try Device.make(from: device!) : nil, @@ -252,6 +232,24 @@ extension Workout: Payload { harmonized: try Harmonized.make(from: harmonized) ) } + public static func collect( + results: [HKSample] + ) -> [Workout] { + var samples = [Workout]() + if let workouts = results as? [HKWorkout] { + for workout in workouts { + do { + let sample = try Workout( + workout: workout + ) + samples.append(sample) + } catch { + continue + } + } + } + return samples + } } // MARK: - Payload extension Workout.Harmonized: Payload { @@ -272,7 +270,7 @@ extension Workout.Harmonized: Payload { let totalDistance = dictionary["totalDistance"] as? NSNumber let totalSwimmingStrokeCount = dictionary["totalSwimmingStrokeCount"] as? NSNumber let totalFlightsClimbed = dictionary["totalFlightsClimbed"] as? NSNumber - let metadata = dictionary["metadata"] as? [String: String] + let metadata = dictionary["metadata"] as? [String: Any] return Workout.Harmonized( value: value, description: description, @@ -292,7 +290,7 @@ extension Workout.Harmonized: Payload { ? Double(truncating: totalFlightsClimbed!) : nil, totalFlightsClimbedUnit: totalFlightsClimbedUnit, - metadata: metadata + metadata: metadata?.asMetadata ) } } diff --git a/Sources/Model/Payload/WorkoutConfiguration.swift b/Sources/Model/Payload/WorkoutConfiguration.swift index 38d4ceb..0d6b422 100644 --- a/Sources/Model/Payload/WorkoutConfiguration.swift +++ b/Sources/Model/Payload/WorkoutConfiguration.swift @@ -5,7 +5,6 @@ // Created by Victor on 25.09.20. // -import Foundation import HealthKit @available(iOS 10.0, *) diff --git a/Sources/Model/Payload/WorkoutEvent.swift b/Sources/Model/Payload/WorkoutEvent.swift index 09fa1a3..9cd54de 100644 --- a/Sources/Model/Payload/WorkoutEvent.swift +++ b/Sources/Model/Payload/WorkoutEvent.swift @@ -5,16 +5,15 @@ // Created by Victor on 25.09.20. // -import Foundation import HealthKit public struct WorkoutEvent: Sample { public struct Harmonized: Codable { public let value: Int public let description: String - public let metadata: [String: String]? + public let metadata: Metadata? - public init(value: Int, description: String, metadata: [String: String]?) { + public init(value: Int, description: String, metadata: Metadata?) { self.value = value self.description = description self.metadata = metadata @@ -23,7 +22,7 @@ public struct WorkoutEvent: Sample { public func copyWith( value: Int? = nil, description: String? = nil, - metadata: [String: String]? = nil + metadata: Metadata? = nil ) -> Harmonized { return Harmonized( value: value ?? self.value, @@ -97,7 +96,7 @@ extension WorkoutEvent: Original { start: startTimestamp.asDate, end: endTimestamp.asDate ), - metadata: harmonized.metadata + metadata: harmonized.metadata?.original ) } } @@ -112,11 +111,11 @@ extension WorkoutEvent.Harmonized: Payload { else { throw HealthKitError.invalidValue("Invalid dictionary: \(dictionary)") } - let metadata = dictionary["metadata"] as? [String: String] - return WorkoutEvent.Harmonized( + let metadata = dictionary["metadata"] as? [String: Any] + return WorkoutEvent.Harmonized( value: value, description: description, - metadata: metadata + metadata: metadata?.asMetadata ) } } @@ -134,8 +133,8 @@ extension WorkoutEvent: Payload { throw HealthKitError.invalidValue("Invalid dictionary: \(dictionary)") } return WorkoutEvent( - startTimestamp: Double(truncating: startTimestamp).secondsSince1970, - endTimestamp: Double(truncating: endTimestamp).secondsSince1970, + startTimestamp: Double(truncating: startTimestamp), + endTimestamp: Double(truncating: endTimestamp), duration: Double(truncating: duration), harmonized: try WorkoutEvent.Harmonized.make(from: harmonized) ) diff --git a/Sources/Model/Payload/WorkoutRoute.swift b/Sources/Model/Payload/WorkoutRoute.swift index c1bdb11..2d5ab1a 100644 --- a/Sources/Model/Payload/WorkoutRoute.swift +++ b/Sources/Model/Payload/WorkoutRoute.swift @@ -5,10 +5,24 @@ // Created by Victor on 24.11.20. // -import Foundation +import HealthKit import CoreLocation -public struct WorkoutRoute: Codable { +@available(iOS 11.0, *) +public struct WorkoutRoute: Identifiable, Sample { + public struct Route: Codable { + public let locations: [Location] + public let done: Bool + + public init( + locations: [Location], + done: Bool + ) { + self.locations = locations + self.done = done + } + } + public struct Location: Codable { public let latitude: Double public let longitude: Double @@ -18,29 +32,28 @@ public struct WorkoutRoute: Codable { public let floor: Int? public let horizontalAccuracy: Double public let speed: Double - public let speedAccuracy: Double + public let speedAccuracy: Double? public let timestamp: Double public let verticalAccuracy: Double init(location: CLLocation) { - let coordinate = location.coordinate - self.latitude = coordinate.latitude - self.longitude = coordinate.longitude + self.latitude = location.coordinate.latitude + self.longitude = location.coordinate.longitude self.altitude = location.altitude self.course = location.course if #available(iOS 13.4, *) { - self.courseAccuracy = location.courseAccuracy + self.courseAccuracy = !location.courseAccuracy.isNaN + ? location.courseAccuracy + : nil } else { self.courseAccuracy = nil } self.floor = location.floor?.level self.horizontalAccuracy = location.horizontalAccuracy self.speed = location.speed - if #available(iOS 10.0, *) { - self.speedAccuracy = location.speedAccuracy - } else { - self.speedAccuracy = 0 - } + self.speedAccuracy = !location.speedAccuracy.isNaN + ? location.speedAccuracy + : nil self.timestamp = location.timestamp.timeIntervalSince1970 self.verticalAccuracy = location.verticalAccuracy } @@ -54,7 +67,7 @@ public struct WorkoutRoute: Codable { floor: Int?, horizontalAccuracy: Double, speed: Double, - speedAccuracy: Double, + speedAccuracy: Double?, timestamp: Double, verticalAccuracy: Double ) { @@ -72,11 +85,186 @@ public struct WorkoutRoute: Codable { } } - public let locations: [Location] - public let done: Bool + public struct Harmonized: Codable { + public let count: Int + public let routes: [Route] + public let metadata: Metadata? + + public init( + count: Int, + routes: [Route], + metadata: Metadata? + ) { + self.count = count + self.routes = routes + self.metadata = metadata + } + + public func copyWith( + count: Int? = nil, + routes: [Route]? = nil, + metadata: Metadata? = nil + ) -> Harmonized { + return Harmonized( + count: count ?? self.count, + routes: routes ?? self.routes, + metadata: metadata ?? self.metadata + ) + } + } + + public let uuid: String + public let identifier: String + public let startTimestamp: Double + public let endTimestamp: Double + public let device: Device? + public let sourceRevision: SourceRevision + public let harmonized: Harmonized + + public init( + identifier: String, + startTimestamp: Double, + endTimestamp: Double, + device: Device?, + sourceRevision: SourceRevision, + harmonized: Harmonized + ) { + self.uuid = UUID().uuidString + self.identifier = identifier + self.startTimestamp = startTimestamp + self.endTimestamp = endTimestamp + self.device = device + self.sourceRevision = sourceRevision + self.harmonized = harmonized + } - public init(locations: [Location], done: Bool) { - self.locations = locations - self.done = done + init(sample: HKWorkoutRoute, routes: [Route]) { + self.uuid = sample.uuid.uuidString + self.identifier = sample.sampleType.identifier + self.startTimestamp = sample.startDate.timeIntervalSince1970 + self.endTimestamp = sample.endDate.timeIntervalSince1970 + self.device = Device(device: sample.device) + self.sourceRevision = SourceRevision(sourceRevision: sample.sourceRevision) + self.harmonized = sample.harmonize(routes: routes) + } +} +// MARK: - Payload +@available(iOS 11.0, *) +extension WorkoutRoute.Location: Payload { + public static func make(from dictionary: [String: Any]) throws -> WorkoutRoute.Location { + guard + let latitude = dictionary["latitude"] as? NSNumber, + let longitude = dictionary["longitude"] as? NSNumber, + let altitude = dictionary["altitude"] as? NSNumber, + let course = dictionary["course"] as? NSNumber, + let horizontalAccuracy = dictionary["horizontalAccuracy"] as? NSNumber, + let speed = dictionary["speed"] as? NSNumber, + let timestamp = dictionary["timestamp"] as? NSNumber, + let verticalAccuracy = dictionary["verticalAccuracy"] as? NSNumber + else { + throw HealthKitError.invalidValue("Invalid dictionary: \(dictionary)") + } + let floor = dictionary["floor"] as? NSNumber + let courseAccuracy = dictionary["courseAccuracy"] as? NSNumber + let speedAccuracy = dictionary["speedAccuracy"] as? NSNumber + return WorkoutRoute.Location( + latitude: Double(truncating: latitude), + longitude: Double(truncating: longitude), + altitude: Double(truncating: altitude), + course: Double(truncating: course), + courseAccuracy: courseAccuracy != nil + ? Double(truncating: courseAccuracy!) + : nil, + floor: floor != nil + ? Int(truncating: floor!) + : nil, + horizontalAccuracy: Double(truncating: horizontalAccuracy), + speed: Double(truncating: speed), + speedAccuracy: speedAccuracy != nil + ? Double(truncating: speedAccuracy!) + : nil, + timestamp: Double(truncating: timestamp), + verticalAccuracy: Double(truncating: verticalAccuracy) + ) + } + public static func collect(from array: [Any]) throws -> [WorkoutRoute.Location] { + var locations = [WorkoutRoute.Location]() + for element in array { + if let dictionary = element as? [String: Any] { + let location = try WorkoutRoute.Location.make(from: dictionary) + locations.append(location) + } + } + return locations + } +} +// MARK: - Payload +@available(iOS 11.0, *) +extension WorkoutRoute: Payload { + public static func make(from dictionary: [String: Any]) throws -> WorkoutRoute { + guard + let identifier = dictionary["identifier"] as? String, + let startTimestamp = dictionary["startTimestamp"] as? NSNumber, + let endTimestamp = dictionary["endTimestamp"] as? NSNumber, + let sourceRevision = dictionary["sourceRevision"] as? [String: Any], + let harmonized = dictionary["harmonized"] as? [String: Any] + else { + throw HealthKitError.invalidValue("Invalid dictionary: \(dictionary)") + } + let device = dictionary["device"] as? [String: Any] + return WorkoutRoute( + identifier: identifier, + startTimestamp: Double(truncating: startTimestamp), + endTimestamp: Double(truncating: endTimestamp), + device: device != nil + ? try Device.make(from: device!) + : nil, + sourceRevision: try SourceRevision.make(from: sourceRevision), + harmonized: try Harmonized.make(from: harmonized) + ) + } +} +// MARK: - Payload +@available(iOS 11.0, *) +extension WorkoutRoute.Harmonized: Payload { + public static func make(from dictionary: [String: Any]) throws -> WorkoutRoute.Harmonized { + guard + let count = dictionary["count"] as? Int, + let routes = dictionary["routes"] as? [Any] + else { + throw HealthKitError.invalidValue("Invalid dictionary: \(dictionary)") + } + let metadata = dictionary["metadata"] as? [String: Any] + return WorkoutRoute.Harmonized( + count: count, + routes: try WorkoutRoute.Route.collect(from: routes), + metadata: metadata?.asMetadata + ) + } +} +// MARK: - Payload +@available(iOS 11.0, *) +extension WorkoutRoute.Route: Payload { + public static func make(from dictionary: [String: Any]) throws -> WorkoutRoute.Route { + guard + let locations = dictionary["locations"] as? [Any], + let done = dictionary["done"] as? Bool + else { + throw HealthKitError.invalidValue("Invalid dictionary: \(dictionary)") + } + return WorkoutRoute.Route( + locations: try WorkoutRoute.Location.collect(from: locations), + done: done + ) + } + public static func collect(from array: [Any]) throws -> [WorkoutRoute.Route] { + var routes = [WorkoutRoute.Route]() + for element in array { + if let dictionary = element as? [String: Any] { + let route = try WorkoutRoute.Route.make(from: dictionary) + routes.append(route) + } + } + return routes } } diff --git a/Sources/Model/PreferredUnit.swift b/Sources/Model/PreferredUnit.swift index c46f950..927d9dc 100644 --- a/Sources/Model/PreferredUnit.swift +++ b/Sources/Model/PreferredUnit.swift @@ -5,7 +5,6 @@ // Created by Victor on 16.11.20. // -import Foundation import HealthKit public struct PreferredUnit: Codable { @@ -22,7 +21,7 @@ public struct PreferredUnit: Codable { self.unit = unit } } -// MARK: - Factory +// MARK: - Payload public extension PreferredUnit { static func collect( from dictionary: [HKQuantityType : HKUnit] @@ -55,9 +54,7 @@ public extension PreferredUnit { } // MARK: - Payload extension PreferredUnit: Payload { - public static func make( - from dictionary: [String : Any] - ) throws -> PreferredUnit { + public static func make(from dictionary: [String: Any]) throws -> PreferredUnit { guard let identifier = dictionary["identifier"] as? String, let unit = dictionary["unit"] as? String diff --git a/Sources/Model/Type/ActivitySummaryType.swift b/Sources/Model/Type/ActivitySummaryType.swift index 1a9fdbe..5d8b8c9 100644 --- a/Sources/Model/Type/ActivitySummaryType.swift +++ b/Sources/Model/Type/ActivitySummaryType.swift @@ -5,7 +5,6 @@ // Created by Victor on 05.10.20. // -import Foundation import HealthKit /** diff --git a/Sources/Model/Type/CharacteristicType.swift b/Sources/Model/Type/CharacteristicType.swift index 4e492fa..e7e9a07 100644 --- a/Sources/Model/Type/CharacteristicType.swift +++ b/Sources/Model/Type/CharacteristicType.swift @@ -5,7 +5,6 @@ // Created by Victor on 05.10.20. // -import Foundation import HealthKit /** diff --git a/Sources/Model/Type/ObjectType.swift b/Sources/Model/Type/ObjectType.swift index ccd4a9f..3ff60ff 100644 --- a/Sources/Model/Type/ObjectType.swift +++ b/Sources/Model/Type/ObjectType.swift @@ -5,7 +5,6 @@ // Created by Victor on 05.10.20. // -import Foundation import HealthKit public protocol ObjectType { diff --git a/Sources/Model/Type/Sample/CategoryType.swift b/Sources/Model/Type/Sample/CategoryType.swift index dfc9e4a..867bc87 100644 --- a/Sources/Model/Type/Sample/CategoryType.swift +++ b/Sources/Model/Type/Sample/CategoryType.swift @@ -5,7 +5,6 @@ // Created by Victor on 05.10.20. // -import Foundation import HealthKit /** @@ -71,6 +70,13 @@ public enum CategoryType: Int, CaseIterable, SampleType { case vaginalDryness case vomiting case wheezing + case pregnancyTestResult + case progesteroneTestResult + case persistentIntermenstrualBleeding + case prolongedMenstrualPeriods + case irregularMenstrualCycles + case infrequentMenstrualCycles + case appleWalkingSteadinessEvent public var identifier: String? { return original?.identifier @@ -95,315 +101,240 @@ public enum CategoryType: Int, CaseIterable, SampleType { case .audioExposureEvent: if #available(iOS 13.0, *) { return HKObjectType.categoryType(forIdentifier: .audioExposureEvent) - } else { - return nil } case .mindfulSession: if #available(iOS 10.0, *) { return HKObjectType.categoryType(forIdentifier: .mindfulSession) - } else { - return nil } case .highHeartRateEvent: if #available(iOS 12.2, *) { return HKObjectType.categoryType(forIdentifier: .highHeartRateEvent) - } else { - return nil } case .lowHeartRateEvent: if #available(iOS 12.2, *) { return HKObjectType.categoryType(forIdentifier: .lowHeartRateEvent) - } else { - return nil } case .irregularHeartRhythmEvent: if #available(iOS 12.2, *) { return HKObjectType.categoryType(forIdentifier: .irregularHeartRhythmEvent) - } else { - return nil } case .toothbrushingEvent: if #available(iOS 13.0, *) { return HKObjectType.categoryType(forIdentifier: .toothbrushingEvent) - } else { - return nil } case .pregnancy: if #available(iOS 14.3, *) { return HKObjectType.categoryType(forIdentifier: .pregnancy) - } else { - return nil } case .lactation: if #available(iOS 14.3, *) { return HKObjectType.categoryType(forIdentifier: .lactation) - } else { - return nil } case .contraceptive: if #available(iOS 14.3, *) { return HKObjectType.categoryType(forIdentifier: .contraceptive) - } else { - return nil } case .environmentalAudioExposureEvent: if #available(iOS 14.0, *) { return HKObjectType.categoryType(forIdentifier: .environmentalAudioExposureEvent) - } else { - return nil } case .headphoneAudioExposureEvent: if #available(iOS 14.2, *) { return HKObjectType.categoryType(forIdentifier: .headphoneAudioExposureEvent) - } else { - return nil } case .handwashingEvent: if #available(iOS 14.0, *) { return HKObjectType.categoryType(forIdentifier: .handwashingEvent) - } else { - return nil } case .lowCardioFitnessEvent: if #available(iOS 14.3, *) { return HKObjectType.categoryType(forIdentifier: .lowCardioFitnessEvent) - } else { - return nil } case .abdominalCramps: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .abdominalCramps) - } else { - return nil } case .acne: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .acne) - } else { - return nil } case .appetiteChanges: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .appetiteChanges) - } else { - return nil } case .bladderIncontinence: if #available(iOS 14.0, *) { return HKObjectType.categoryType(forIdentifier: .bladderIncontinence) - } else { - return nil } case .bloating: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .bloating) - } else { - return nil } case .breastPain: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .breastPain) - } else { - return nil } case .chestTightnessOrPain: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .chestTightnessOrPain) - } else { - return nil } case .chills: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .chills) - } else { - return nil } case .constipation: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .constipation) - } else { - return nil } case .coughing: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .coughing) - } else { - return nil } case .diarrhea: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .diarrhea) - } else { - return nil } case .dizziness: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .dizziness) - } else { - return nil } case .drySkin: if #available(iOS 14.0, *) { return HKObjectType.categoryType(forIdentifier: .drySkin) - } else { - return nil } case .fainting: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .fainting) - } else { - return nil } case .fatigue: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .fatigue) - } else { - return nil } case .fever: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .fever) - } else { - return nil } case .generalizedBodyAche: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .generalizedBodyAche) - } else { - return nil } case .hairLoss: if #available(iOS 14.0, *) { return HKObjectType.categoryType(forIdentifier: .hairLoss) - } else { - return nil } case .headache: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .headache) - } else { - return nil } case .heartburn: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .heartburn) - } else { - return nil } case .hotFlashes: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .hotFlashes) - } else { - return nil } case .lossOfSmell: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .lossOfSmell) - } else { - return nil } case .lossOfTaste: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .lossOfTaste) - } else { - return nil } case .lowerBackPain: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .lowerBackPain) - } else { - return nil } case .memoryLapse: if #available(iOS 14.0, *) { return HKObjectType.categoryType(forIdentifier: .memoryLapse) - } else { - return nil } case .moodChanges: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .moodChanges) - } else { - return nil } case .nausea: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .nausea) - } else { - return nil } case .nightSweats: if #available(iOS 14.0, *) { return HKObjectType.categoryType(forIdentifier: .nightSweats) - } else { - return nil } case .pelvicPain: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .pelvicPain) - } else { - return nil } case .rapidPoundingOrFlutteringHeartbeat: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .rapidPoundingOrFlutteringHeartbeat) - } else { - return nil } case .runnyNose: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .runnyNose) - } else { - return nil } case .shortnessOfBreath: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .shortnessOfBreath) - } else { - return nil } case .sinusCongestion: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .sinusCongestion) - } else { - return nil } case .skippedHeartbeat: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .skippedHeartbeat) - } else { - return nil } case .sleepChanges: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .sleepChanges) - } else { - return nil } case .soreThroat: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .soreThroat) - } else { - return nil } case .vaginalDryness: if #available(iOS 14.0, *) { return HKObjectType.categoryType(forIdentifier: .vaginalDryness) - } else { - return nil } case .vomiting: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .vomiting) - } else { - return nil } case .wheezing: if #available(iOS 13.6, *) { return HKObjectType.categoryType(forIdentifier: .wheezing) - } else { - return nil + } + case .pregnancyTestResult: + if #available(iOS 15.0, *) { + return HKObjectType.categoryType(forIdentifier: .pregnancyTestResult) + } + case .progesteroneTestResult: + if #available(iOS 15.0, *) { + return HKObjectType.categoryType(forIdentifier: .progesteroneTestResult) + } + case .persistentIntermenstrualBleeding: + if #available(iOS 16.0, *) { + return HKObjectType.categoryType(forIdentifier: .persistentIntermenstrualBleeding) + } + case .prolongedMenstrualPeriods: + if #available(iOS 16.0, *) { + return HKObjectType.categoryType(forIdentifier: .prolongedMenstrualPeriods) + } + case .irregularMenstrualCycles: + if #available(iOS 16.0, *) { + return HKObjectType.categoryType(forIdentifier: .irregularMenstrualCycles) + } + case .infrequentMenstrualCycles: + if #available(iOS 16.0, *) { + return HKObjectType.categoryType(forIdentifier: .infrequentMenstrualCycles) + } + case .appleWalkingSteadinessEvent: + if #available(iOS 15.0, *) { + return HKObjectType.categoryType(forIdentifier: .appleWalkingSteadinessEvent) } } + return nil } } diff --git a/Sources/Model/Type/Sample/ClinicalType.swift b/Sources/Model/Type/Sample/ClinicalType.swift new file mode 100644 index 0000000..b79e6ab --- /dev/null +++ b/Sources/Model/Type/Sample/ClinicalType.swift @@ -0,0 +1,44 @@ +// +// SampleType.swift +// HealthKitReporter +// +// Created by Quentin on 01.08.24. +// + +import HealthKit + +public enum ClinicalType: Int, CaseIterable, SampleType { + case allergyRecord + case conditionRecord + case immunizationRecord + case labResultRecord + case medicationRecord + case procedureRecord + case vitalSignRecord + + public var identifier: String? { + return original?.identifier + } + + public var original: HKObjectType? { + if #available(iOS 12.0, *) { + switch self { + case .allergyRecord: + return HKObjectType.clinicalType(forIdentifier: .allergyRecord) + case .conditionRecord: + return HKObjectType.clinicalType(forIdentifier: .conditionRecord) + case .immunizationRecord: + return HKObjectType.clinicalType(forIdentifier: .immunizationRecord) + case .labResultRecord: + return HKObjectType.clinicalType(forIdentifier: .labResultRecord) + case .medicationRecord: + return HKObjectType.clinicalType(forIdentifier: .medicationRecord) + case .procedureRecord: + return HKObjectType.clinicalType(forIdentifier: .procedureRecord) + case .vitalSignRecord: + return HKObjectType.clinicalType(forIdentifier: .vitalSignRecord) + } + } + return nil + } +} diff --git a/Sources/Model/Type/Sample/CorrelationType.swift b/Sources/Model/Type/Sample/CorrelationType.swift index b048519..5ab733a 100644 --- a/Sources/Model/Type/Sample/CorrelationType.swift +++ b/Sources/Model/Type/Sample/CorrelationType.swift @@ -5,7 +5,6 @@ // Created by Victor on 05.10.20. // -import Foundation import HealthKit /** diff --git a/Sources/Model/Type/Sample/DocumentType.swift b/Sources/Model/Type/Sample/DocumentType.swift index 4660dd4..480a2fa 100644 --- a/Sources/Model/Type/Sample/DocumentType.swift +++ b/Sources/Model/Type/Sample/DocumentType.swift @@ -5,7 +5,6 @@ // Created by Victor on 05.10.20. // -import Foundation import HealthKit /** diff --git a/Sources/Model/Type/Sample/ElectrocardiogramType.swift b/Sources/Model/Type/Sample/ElectrocardiogramType.swift index 49893d5..e46c2a5 100644 --- a/Sources/Model/Type/Sample/ElectrocardiogramType.swift +++ b/Sources/Model/Type/Sample/ElectrocardiogramType.swift @@ -5,13 +5,11 @@ // Created by Victor on 05.10.20. // -import Foundation import HealthKit /** All HealthKit electrocardiogram types */ -@available(iOS 14.0, *) public enum ElectrocardiogramType: Int, CaseIterable, SampleType { case electrocardiogramType @@ -22,7 +20,10 @@ public enum ElectrocardiogramType: Int, CaseIterable, SampleType { public var original: HKObjectType? { switch self { case .electrocardiogramType: - return HKObjectType.electrocardiogramType() + if #available(iOS 14.0, *) { + return HKObjectType.electrocardiogramType() + } } + return nil } } diff --git a/Sources/Model/Type/Sample/QuantityType.swift b/Sources/Model/Type/Sample/QuantityType.swift index 7a6b3bb..98f03c6 100644 --- a/Sources/Model/Type/Sample/QuantityType.swift +++ b/Sources/Model/Type/Sample/QuantityType.swift @@ -5,7 +5,6 @@ // Created by Victor on 05.10.20. // -import Foundation import HealthKit /** @@ -102,6 +101,20 @@ public enum QuantityType: Int, CaseIterable, SampleType { case dietaryCaffeine case dietaryWater case uvExposure + case appleMoveTime + case appleWalkingSteadiness + case appleSleepingWristTemperature + case runningStrideLength + case runningVerticalOscillation + case runningGroundContactTime + case runningPower + case runningSpeed + case heartRateRecoveryOneMinute + case numberOfAlcoholicBeverages + case atrialFibrillationBurden + case underwaterDepth + case waterTemperature + public var identifier: String? { return original?.identifier @@ -112,8 +125,6 @@ public enum QuantityType: Int, CaseIterable, SampleType { case .heartRateVariabilitySDNN: if #available(iOS 11.0, *) { return HKObjectType.quantityType(forIdentifier: .heartRateVariabilitySDNN) - } else { - return nil } case .bodyMassIndex: return HKObjectType.quantityType(forIdentifier: .bodyMassIndex) @@ -142,28 +153,20 @@ public enum QuantityType: Int, CaseIterable, SampleType { case .restingHeartRate: if #available(iOS 11.0, *) { return HKObjectType.quantityType(forIdentifier: .restingHeartRate) - } else { - return nil } case .vo2Max: if #available(iOS 11.0, *) { return HKObjectType.quantityType(forIdentifier: .vo2Max) - } else { - return nil } case .waistCircumference: if #available(iOS 11.0, *) { return HKObjectType.quantityType(forIdentifier: .waistCircumference) - } else { - return nil } case .stepCount: return HKObjectType.quantityType(forIdentifier: .stepCount) case .distanceSwimming: if #available(iOS 10.0, *) { return HKObjectType.quantityType(forIdentifier: .distanceSwimming) - } else { - return nil } case .distanceWalkingRunning: return HKObjectType.quantityType(forIdentifier: .distanceWalkingRunning) @@ -178,8 +181,6 @@ public enum QuantityType: Int, CaseIterable, SampleType { case .appleExerciseTime: if #available(iOS 9.3, *) { return HKObjectType.quantityType(forIdentifier: .appleExerciseTime) - } else { - return nil } case .dietaryEnergyConsumed: return HKObjectType.quantityType(forIdentifier: .dietaryEnergyConsumed) @@ -246,34 +247,24 @@ public enum QuantityType: Int, CaseIterable, SampleType { case .distanceWheelchair: if #available(iOS 10.0, *) { return HKObjectType.quantityType(forIdentifier: .distanceWheelchair) - } else { - return nil } case .nikeFuel: return HKObjectType.quantityType(forIdentifier: .nikeFuel) case .pushCount: if #available(iOS 10.0, *) { return HKObjectType.quantityType(forIdentifier: .pushCount) - } else { - return nil } case .swimmingStrokeCount: if #available(iOS 10.0, *) { return HKObjectType.quantityType(forIdentifier: .swimmingStrokeCount) - } else { - return nil } case .distanceDownhillSnowSports: if #available(iOS 11.2, *) { return HKObjectType.quantityType(forIdentifier: .distanceDownhillSnowSports) - } else { - return nil } case .walkingHeartRateAverage: if #available(iOS 11.0, *) { return HKObjectType.quantityType(forIdentifier: .walkingHeartRateAverage) - } else { - return nil } case .peripheralPerfusionIndex: return HKObjectType.quantityType(forIdentifier: .peripheralPerfusionIndex) @@ -286,8 +277,6 @@ public enum QuantityType: Int, CaseIterable, SampleType { case .insulinDelivery: if #available(iOS 11.0, *) { return HKObjectType.quantityType(forIdentifier: .insulinDelivery) - } else { - return nil } case .bloodAlcoholContent: return HKObjectType.quantityType(forIdentifier: .bloodAlcoholContent) @@ -320,63 +309,96 @@ public enum QuantityType: Int, CaseIterable, SampleType { case .environmentalAudioExposure: if #available(iOS 13.0, *) { return HKObjectType.quantityType(forIdentifier: .environmentalAudioExposure) - } else { - return nil } case .headphoneAudioExposure: if #available(iOS 13.0, *) { return HKObjectType.quantityType(forIdentifier: .headphoneAudioExposure) - } else { - return nil } case .appleStandTime: if #available(iOS 13.0, *) { return HKObjectType.quantityType(forIdentifier: .appleStandTime) - } else { - return nil } case .walkingSpeed: if #available(iOS 14.0, *) { return HKObjectType.quantityType(forIdentifier: .walkingSpeed) - } else { - return nil } case .walkingDoubleSupportPercentage: if #available(iOS 14.0, *) { return HKObjectType.quantityType(forIdentifier: .walkingDoubleSupportPercentage) - } else { - return nil } case .walkingAsymmetryPercentage: if #available(iOS 14.0, *) { return HKObjectType.quantityType(forIdentifier: .walkingAsymmetryPercentage) - } else { - return nil } case .walkingStepLength: if #available(iOS 14.0, *) { return HKObjectType.quantityType(forIdentifier: .walkingStepLength) - } else { - return nil } case .sixMinuteWalkTestDistance: if #available(iOS 14.0, *) { return HKObjectType.quantityType(forIdentifier: .sixMinuteWalkTestDistance) - } else { - return nil } case .stairAscentSpeed: if #available(iOS 14.0, *) { return HKObjectType.quantityType(forIdentifier: .stairAscentSpeed) - } else { - return nil } case .stairDescentSpeed: if #available(iOS 14.0, *) { return HKObjectType.quantityType(forIdentifier: .stairDescentSpeed) - } else { - return nil + } + case .appleMoveTime: + if #available(iOS 14.5, *) { + return HKObjectType.quantityType(forIdentifier: .appleMoveTime) + } + case .appleWalkingSteadiness: + if #available(iOS 15.0, *) { + return HKObjectType.quantityType(forIdentifier: .appleWalkingSteadiness) + } + case .appleSleepingWristTemperature: + if #available(iOS 16.0, *) { + return HKObjectType.quantityType(forIdentifier: .appleSleepingWristTemperature) + } + case .runningStrideLength: + if #available(iOS 16.0, *) { + return HKObjectType.quantityType(forIdentifier: .runningStrideLength) + } + case .runningVerticalOscillation: + if #available(iOS 16.0, *) { + return HKObjectType.quantityType(forIdentifier: .runningVerticalOscillation) + } + case .runningGroundContactTime: + if #available(iOS 16.0, *) { + return HKObjectType.quantityType(forIdentifier: .runningGroundContactTime) + } + case .runningPower: + if #available(iOS 16.0, *) { + return HKObjectType.quantityType(forIdentifier: .runningPower) + } + case .runningSpeed: + if #available(iOS 16.0, *) { + return HKObjectType.quantityType(forIdentifier: .runningSpeed) + } + case .heartRateRecoveryOneMinute: + if #available(iOS 16.0, *) { + return HKObjectType.quantityType(forIdentifier: .heartRateRecoveryOneMinute) + } + case .numberOfAlcoholicBeverages: + if #available(iOS 15.0, *) { + return HKObjectType.quantityType(forIdentifier: .numberOfAlcoholicBeverages) + } + case .atrialFibrillationBurden: + if #available(iOS 16.0, *) { + return HKObjectType.quantityType(forIdentifier: .atrialFibrillationBurden) + } + case .underwaterDepth: + if #available(iOS 16.0, *) { + return HKObjectType.quantityType(forIdentifier: .underwaterDepth) + } + case .waterTemperature: + if #available(iOS 16.0, *) { + return HKObjectType.quantityType(forIdentifier: .waterTemperature) } } + return nil } } diff --git a/Sources/Model/Type/Sample/SampleType.swift b/Sources/Model/Type/Sample/SampleType.swift index 9886608..65fec74 100644 --- a/Sources/Model/Type/Sample/SampleType.swift +++ b/Sources/Model/Type/Sample/SampleType.swift @@ -5,7 +5,6 @@ // Created by Victor on 18.11.20. // -import Foundation import HealthKit public protocol SampleType: ObjectType { diff --git a/Sources/Model/Type/Sample/SeriesType.swift b/Sources/Model/Type/Sample/SeriesType.swift index c1b15ce..6728ad6 100644 --- a/Sources/Model/Type/Sample/SeriesType.swift +++ b/Sources/Model/Type/Sample/SeriesType.swift @@ -5,7 +5,6 @@ // Created by Victor on 05.10.20. // -import Foundation import HealthKit /** diff --git a/Sources/Model/Type/Sample/VisionPrescriptionType.swift b/Sources/Model/Type/Sample/VisionPrescriptionType.swift new file mode 100644 index 0000000..71fb2c8 --- /dev/null +++ b/Sources/Model/Type/Sample/VisionPrescriptionType.swift @@ -0,0 +1,29 @@ +// +// VisionPrescriptionType.swift +// HealthKitReporter +// +// Created by Victor Kachalov on 04.10.22. +// + +import HealthKit + +/** + All HealthKit vision prescription types + */ +public enum VisionPrescriptionType: Int, CaseIterable, SampleType { + case visionPrescription + + public var identifier: String? { + return original?.identifier + } + + public var original: HKObjectType? { + switch self { + case .visionPrescription: + if #available(iOS 16.0, *) { + return HKObjectType.visionPrescriptionType() + } + } + return nil + } +} diff --git a/Sources/Model/Type/Sample/WorkoutType.swift b/Sources/Model/Type/Sample/WorkoutType.swift index 8fa58e3..5a87aff 100644 --- a/Sources/Model/Type/Sample/WorkoutType.swift +++ b/Sources/Model/Type/Sample/WorkoutType.swift @@ -5,7 +5,6 @@ // Created by Victor on 05.10.20. // -import Foundation import HealthKit /** diff --git a/Sources/Model/UnitConvertable.swift b/Sources/Model/UnitConvertable.swift index 4436888..2b91c32 100644 --- a/Sources/Model/UnitConvertable.swift +++ b/Sources/Model/UnitConvertable.swift @@ -6,7 +6,6 @@ // import Foundation -import HealthKit public protocol UnitConvertable { func converted(to unit: String) throws -> Self diff --git a/Sources/Model/UpdateFrequency.swift b/Sources/Model/UpdateFrequency.swift index 33d2e56..1551982 100644 --- a/Sources/Model/UpdateFrequency.swift +++ b/Sources/Model/UpdateFrequency.swift @@ -5,7 +5,6 @@ // Created by Victor on 13.11.20. // -import Foundation import HealthKit public enum UpdateFrequency: Int { diff --git a/Sources/Service/HealthKitManager.swift b/Sources/Service/HealthKitManager.swift index c296388..3981cc2 100644 --- a/Sources/Service/HealthKitManager.swift +++ b/Sources/Service/HealthKitManager.swift @@ -5,7 +5,6 @@ // Created by Victor on 25.09.20. // -import Foundation import HealthKit /// **HealthKitManager** class for HK managing operations diff --git a/Sources/Service/HealthKitObserver.swift b/Sources/Service/HealthKitObserver.swift index 591e49f..3418c9b 100644 --- a/Sources/Service/HealthKitObserver.swift +++ b/Sources/Service/HealthKitObserver.swift @@ -5,7 +5,6 @@ // Created by Victor on 23.09.20. // -import Foundation import HealthKit /// **HealthKitObserver** class for HK observing operations diff --git a/Sources/Service/HealthKitReader.swift b/Sources/Service/HealthKitReader.swift index 87bf682..612baee 100644 --- a/Sources/Service/HealthKitReader.swift +++ b/Sources/Service/HealthKitReader.swift @@ -5,7 +5,6 @@ // Created by Victor on 23.09.20. // -import Foundation import HealthKit @available(iOS 9.3, *) @@ -253,6 +252,7 @@ public class HealthKitReader { - Parameter predicate: **NSPredicate** predicate (optional). allSamples by default - Parameter sortDescriptors: array of **NSSortDescriptor** sort descriptors. By default sorting by startData without ascending - Parameter limit: **Int** limit of the elements. HKObjectQueryNoLimit by default + - Parameter withVoltageMeasurements: the query will show the count of made measurements, and if set to **true** will provide ECG with voltage measurments array. By default with **false** the count of measurements will be still available, but the measurements array will be empty. - Parameter resultsHandler: returns a block with samples - Throws: HealthKitError.invalidType */ @@ -266,42 +266,16 @@ public class HealthKitReader { ) ], limit: Int = HKObjectQueryNoLimit, + withVoltageMeasurements: Bool = false, resultsHandler: @escaping ElectrocardiogramResultsHandler ) throws -> SampleQuery { return try ElectrocardiogramRetriever().makeElectrocardiogramQuery( - predicate: predicate, - sortDescriptors: sortDescriptors, - limit: limit, - resultsHandler: resultsHandler - ) - } - /** - Queries electrocardiogram. - - Parameter predicate: **NSPredicate** predicate (optional). allSamples by default - - Parameter sortDescriptors: array of **NSSortDescriptor** sort descriptors. By default sorting by startData without ascending - - Parameter limit: **Int** limit of the elements. HKObjectQueryNoLimit by default - - Parameter dataHandler: returns a block with voltage measurement for each - iteration until **done** is True. - - Throws: HealthKitError.invalidType - */ - @available(iOS 14.0, *) - public func electrocardiogramVoltageMeasurementQuery( - predicate: NSPredicate? = .allSamples, - sortDescriptors: [NSSortDescriptor] = [ - NSSortDescriptor( - key: HKSampleSortIdentifierStartDate, - ascending: false - ) - ], - limit: Int = HKObjectQueryNoLimit, - dataHandler: @escaping ElectrocardiogramVoltageMeasurementDataHandler - ) throws -> SampleQuery { - return try ElectrocardiogramRetriever().electrocardiogramVoltageMeasurementQuery( healthStore: healthStore, predicate: predicate, sortDescriptors: sortDescriptors, limit: limit, - dataHandler: dataHandler + withVoltageMeasurements: withVoltageMeasurements, + resultsHandler: resultsHandler ) } /** @@ -518,10 +492,10 @@ public class HealthKitReader { - Parameter predicate: **NSPredicate** predicate (optional). allSamples by default - Parameter sortDescriptors: array of **NSSortDescriptor** sort descriptors. By default sorting by startData without ascending - Parameter limit: **Int** limit of the elements. HKObjectQueryNoLimit by default - - Parameter dataHandler: returns a block with heartbeat series for each - iteration until **done** of **WorkoutRoute** is True. + - Parameter resultsHandler: returns a block with workout routes - Throws: HealthKitError.invalidType */ + @available(iOS 11.0, *) public func workoutRouteQuery( predicate: NSPredicate? = .allSamples, sortDescriptors: [NSSortDescriptor] = [ @@ -531,14 +505,14 @@ public class HealthKitReader { ) ], limit: Int = HKObjectQueryNoLimit, - dataHandler: @escaping WorkoutRouteDataHandler + resultsHandler: @escaping WorkoutRouteResultsDataHandler ) throws -> SampleQuery { return try SeriesSampleRetriever().makeWorkoutRouteQuery( healthStore: healthStore, predicate: predicate, sortDescriptors: sortDescriptors, limit: limit, - dataHandler: dataHandler + resultsHandler: resultsHandler ) } /** diff --git a/Sources/Service/HealthKitWriter.swift b/Sources/Service/HealthKitWriter.swift index 8bb5ea0..d2225ec 100644 --- a/Sources/Service/HealthKitWriter.swift +++ b/Sources/Service/HealthKitWriter.swift @@ -5,7 +5,6 @@ // Created by Victor on 24.09.20. // -import Foundation import HealthKit /// **HealthKitWriter** class for HK writing operations @@ -146,6 +145,9 @@ public class HealthKitWriter { if let workout = sample as? Workout { healthStore.save(try workout.asOriginal(), withCompletion: completion) } + if let correlation = sample as? Correlation { + healthStore.save(try correlation.asOriginal(), withCompletion: completion) + } } catch { completion(false, error) } diff --git a/Sources/Service/Retriever/ElectrocardiogramRetriever.swift b/Sources/Service/Retriever/ElectrocardiogramRetriever.swift index de762da..61c66fa 100644 --- a/Sources/Service/Retriever/ElectrocardiogramRetriever.swift +++ b/Sources/Service/Retriever/ElectrocardiogramRetriever.swift @@ -5,52 +5,17 @@ // Created by Victor on 21.10.20. // -import Foundation import HealthKit @available(iOS 14.0, *) class ElectrocardiogramRetriever { func makeElectrocardiogramQuery( - predicate: NSPredicate?, - sortDescriptors: [NSSortDescriptor], - limit: Int, - resultsHandler: @escaping ElectrocardiogramResultsHandler - ) throws -> HKSampleQuery { - let electrocardiogramType = ElectrocardiogramType.electrocardiogramType - guard - let type = electrocardiogramType.original as? HKElectrocardiogramType - else { - throw HealthKitError.invalidType( - "\(electrocardiogramType) can not be represented as HKElectrocardiogramType" - ) - } - let query = HKSampleQuery( - sampleType: type, - predicate: predicate, - limit: limit, - sortDescriptors: sortDescriptors - ) { (query, data, error) in - guard - error == nil, - let results = data - else { - resultsHandler([], error) - return - } - let samples = Electrocardiogram.collect( - results: results - ) - resultsHandler(samples, nil) - } - return query - } - - func electrocardiogramVoltageMeasurementQuery( healthStore: HKHealthStore, predicate: NSPredicate?, sortDescriptors: [NSSortDescriptor], limit: Int, - dataHandler: @escaping ElectrocardiogramVoltageMeasurementDataHandler + withVoltageMeasurements: Bool, + resultsHandler: @escaping ElectrocardiogramResultsHandler ) throws -> HKSampleQuery { let electrocardiogramType = ElectrocardiogramType.electrocardiogramType guard @@ -70,56 +35,45 @@ class ElectrocardiogramRetriever { error == nil, let results = data as? [HKElectrocardiogram] else { - dataHandler( - nil, - false, - error - ) + resultsHandler([], error) return } - for ecgSample in results { - let voltageQuery = HKElectrocardiogramQuery(ecgSample) { (query, result) in - switch(result) { - case .measurement(let voltageMeasurement): - do { - let value = try Electrocardiogram.VoltageMeasurement( - voltageMeasurement: voltageMeasurement - ) - dataHandler( - value, - false, - nil - ) - } catch { - dataHandler( - nil, - false, - nil - ) + var ecgs: [Electrocardiogram] + switch withVoltageMeasurements { + case true: + ecgs = [] + var ecgsError: Error? + let group = DispatchGroup() + for ecgSample in results { + var measurments = [Electrocardiogram.VoltageMeasurement]() + group.enter() + let voltageQuery = HKElectrocardiogramQuery(ecgSample) { (query, result) in + switch(result) { + case .measurement(let voltageMeasurement): + if let measurment = try? Electrocardiogram.VoltageMeasurement(voltageMeasurement: voltageMeasurement) { + measurments.append(measurment) + } + case .done: + if let ecg = try? Electrocardiogram(electrocardiogram: ecgSample, voltageMeasurements: measurments) { + ecgs.append(ecg) + } + group.leave() + case .error(let error): + ecgsError = error + group.leave() + @unknown default: + ecgsError = HealthKitError.notAvailable("Unknown case of Electrocardiogram.VoltageMeasurement result") + group.leave() } - case .done: - dataHandler( - nil, - true, - nil - ) - case .error(let error): - dataHandler( - nil, - false, - error - ) - @unknown default: - dataHandler( - nil, - false, - HealthKitError.notAvailable( - "Unknown case of Electrocardiogram.VoltageMeasurement result" - ) - ) } + healthStore.execute(voltageQuery) + } + group.notify(queue: .global()) { + resultsHandler(ecgs, ecgsError) } - healthStore.execute(voltageQuery) + case false: + ecgs = Electrocardiogram.collect(results: results) + resultsHandler(ecgs, nil) } } return query diff --git a/Sources/Service/Retriever/SeriesSampleRetriever.swift b/Sources/Service/Retriever/SeriesSampleRetriever.swift index e59eda1..981c231 100644 --- a/Sources/Service/Retriever/SeriesSampleRetriever.swift +++ b/Sources/Service/Retriever/SeriesSampleRetriever.swift @@ -5,7 +5,6 @@ // Created by Victor on 24.11.20. // -import Foundation import HealthKit import CoreLocation @@ -82,19 +81,15 @@ class SeriesSampleRetriever { } return query } + @available(iOS 11.0, *) func makeWorkoutRouteQuery( healthStore: HKHealthStore, predicate: NSPredicate?, sortDescriptors: [NSSortDescriptor], limit: Int, - dataHandler: @escaping WorkoutRouteDataHandler + resultsHandler: @escaping WorkoutRouteResultsDataHandler ) throws -> HKSampleQuery { let workoutRoute = SeriesType.workoutRoute - guard #available(iOS 11.0, *) else { - throw HealthKitError.notAvailable( - "HKSeriesType is not available for the current iOS" - ) - } guard let seriesType = workoutRoute.original as? HKSeriesType else { @@ -112,19 +107,24 @@ class SeriesSampleRetriever { error == nil, let result = data else { - dataHandler(nil, error) + resultsHandler([], error) return } + var workoutRoutes = [WorkoutRoute]() + var workoutRoutesError: Error? + let group = DispatchGroup() for element in result { guard let workoutRoute = element as? HKWorkoutRoute else { - dataHandler( - nil, + resultsHandler( + [], HealthKitError.invalidType( - "Sample \(element) is not HKHeartbeatSeriesSample" + "Sample \(element) is not HKWorkoutRoute" ) ) return } + var routes = [WorkoutRoute.Route]() + group.enter() let workoutRouteQuery = HKWorkoutRouteQuery( route: workoutRoute ) { (query, locations, done, error) in @@ -132,19 +132,28 @@ class SeriesSampleRetriever { error == nil, let locations = locations else { - dataHandler(nil, error) + workoutRoutesError = error + group.leave() return } - let workoutRoute = WorkoutRoute( + let route = WorkoutRoute.Route( locations: locations.map { WorkoutRoute.Location(location: $0) }, done: done ) - dataHandler(workoutRoute, nil) + routes.append(route) + if done { + let workoutRoute = WorkoutRoute(sample: workoutRoute, routes: routes) + workoutRoutes.append(workoutRoute) + group.leave() + } } healthStore.execute(workoutRouteQuery) } + group.notify(queue: .global()) { + resultsHandler(workoutRoutes, workoutRoutesError) + } } return query } diff --git a/Tests/CategoryTests.swift b/Tests/CategoryTests.swift index 48ceba8..039f618 100644 --- a/Tests/CategoryTests.swift +++ b/Tests/CategoryTests.swift @@ -79,8 +79,8 @@ class CategoryTests: XCTestCase { func testCreateFromDictionary() throws { let dictionary: [String: Any] = [ "identifier": "HKCategoryTypeIdentifierSleepAnalysis", - "startTimestamp": 1630618680000, - "endTimestamp": 1630697880000, + "startTimestamp": 1630618680, + "endTimestamp": 1630697880, "device": [ "name": nil, "manufacturer": nil, diff --git a/Tests/CorrelationTests.swift b/Tests/CorrelationTests.swift index 926fbb6..51d07c1 100644 --- a/Tests/CorrelationTests.swift +++ b/Tests/CorrelationTests.swift @@ -9,5 +9,324 @@ import XCTest import HealthKitReporter class CorrelationTests: XCTestCase { - + func testCreateThenEncodeThenDecode() throws { + let startDate = Date(timeIntervalSince1970: 1626884800) + let endDate = startDate.addingTimeInterval(60) + let device = Device( + name: "Guy's iPhone", + manufacturer: "Guy", + model: "6.1.1", + hardwareVersion: "some_0", + firmwareVersion: "some_1", + softwareVersion: "some_2", + localIdentifier: "some_3", + udiDeviceIdentifier: "some_4" + ) + let source = Source( + name: "mySource", + bundleIdentifier: "com.kvs.hkreporter" + ) + let operatingSystem = SourceRevision.OperatingSystem( + majorVersion: 1, + minorVersion: 1, + patchVersion: 1 + ) + let sourceRevision = SourceRevision( + source: source, + version: "1.0.0", + productType: "CocoaPod", + systemVersion: "1.0.0.0", + operatingSystem: operatingSystem + ) + let sys = Quantity( + identifier: QuantityType.bloodPressureSystolic.identifier!, + startTimestamp: startDate.timeIntervalSince1970, + endTimestamp: endDate.timeIntervalSince1970, + device: device, + sourceRevision: sourceRevision, + harmonized: Quantity.Harmonized( + value: 123.0, + unit: "mmHg", + metadata: ["you": "saved it"] + ) + ) + let dias = Quantity( + identifier: QuantityType.bloodPressureDiastolic.identifier!, + startTimestamp: startDate.timeIntervalSince1970, + endTimestamp: endDate.timeIntervalSince1970, + device: device, + sourceRevision: sourceRevision, + harmonized: Quantity.Harmonized( + value: 83.0, + unit: "mmHg", + metadata: ["you": "saved it"] + ) + ) + let sut = Correlation( + identifier: CorrelationType.bloodPressure.identifier!, + startTimestamp: startDate.timeIntervalSince1970, + endTimestamp: endDate.timeIntervalSince1970, + device: device, sourceRevision: sourceRevision, + harmonized: Correlation.Harmonized( + quantitySamples: [sys, dias], + categorySamples: [], + metadata: ["you": "saved it"] + ) + ) + let encoded = try sut.encoded() + let decoded = try JSONDecoder().decode( + Correlation.self, + from: encoded.data(using: .utf8)! + ) + XCTAssertEqual(decoded.identifier, "HKCorrelationTypeIdentifierBloodPressure") + XCTAssertEqual(decoded.startTimestamp, 1626884800) + XCTAssertEqual(decoded.endTimestamp, 1626884800 + 60) + XCTAssertEqual(decoded.device?.name, "Guy's iPhone") + XCTAssertEqual(decoded.device?.manufacturer, "Guy") + XCTAssertEqual(decoded.device?.model, "6.1.1") + XCTAssertEqual(decoded.device?.hardwareVersion, "some_0") + XCTAssertEqual(decoded.device?.firmwareVersion, "some_1") + XCTAssertEqual(decoded.device?.softwareVersion, "some_2") + XCTAssertEqual(decoded.device?.localIdentifier, "some_3") + XCTAssertEqual(decoded.device?.udiDeviceIdentifier, "some_4") + XCTAssertEqual(decoded.sourceRevision.source.name, "mySource") + XCTAssertEqual(decoded.sourceRevision.source.bundleIdentifier, "com.kvs.hkreporter") + XCTAssertEqual(decoded.sourceRevision.version, "1.0.0") + XCTAssertEqual(decoded.sourceRevision.productType, "CocoaPod") + XCTAssertEqual(decoded.sourceRevision.systemVersion, "1.0.0.0") + XCTAssertEqual(decoded.sourceRevision.operatingSystem.majorVersion, 1) + XCTAssertEqual(decoded.sourceRevision.operatingSystem.minorVersion, 1) + XCTAssertEqual(decoded.sourceRevision.operatingSystem.patchVersion, 1) + XCTAssertEqual(decoded.harmonized.quantitySamples.count, 2) + XCTAssertEqual(decoded.harmonized.quantitySamples[0].identifier, "HKQuantityTypeIdentifierBloodPressureSystolic") + XCTAssertEqual(decoded.harmonized.quantitySamples[0].startTimestamp, 1626884800) + XCTAssertEqual(decoded.harmonized.quantitySamples[0].endTimestamp, 1626884800 + 60) + XCTAssertEqual(decoded.harmonized.quantitySamples[0].device?.name, "Guy's iPhone") + XCTAssertEqual(decoded.harmonized.quantitySamples[0].device?.manufacturer, "Guy") + XCTAssertEqual(decoded.harmonized.quantitySamples[0].device?.model, "6.1.1") + XCTAssertEqual(decoded.harmonized.quantitySamples[0].device?.hardwareVersion, "some_0") + XCTAssertEqual(decoded.harmonized.quantitySamples[0].device?.firmwareVersion, "some_1") + XCTAssertEqual(decoded.harmonized.quantitySamples[0].device?.softwareVersion, "some_2") + XCTAssertEqual(decoded.harmonized.quantitySamples[0].device?.localIdentifier, "some_3") + XCTAssertEqual(decoded.harmonized.quantitySamples[0].device?.udiDeviceIdentifier, "some_4") + XCTAssertEqual(decoded.harmonized.quantitySamples[0].sourceRevision.source.name, "mySource") + XCTAssertEqual(decoded.harmonized.quantitySamples[0].sourceRevision.source.bundleIdentifier, "com.kvs.hkreporter") + XCTAssertEqual(decoded.harmonized.quantitySamples[0].sourceRevision.version, "1.0.0") + XCTAssertEqual(decoded.harmonized.quantitySamples[0].sourceRevision.productType, "CocoaPod") + XCTAssertEqual(decoded.harmonized.quantitySamples[0].sourceRevision.systemVersion, "1.0.0.0") + XCTAssertEqual(decoded.harmonized.quantitySamples[0].sourceRevision.operatingSystem.majorVersion, 1) + XCTAssertEqual(decoded.harmonized.quantitySamples[0].sourceRevision.operatingSystem.minorVersion, 1) + XCTAssertEqual(decoded.harmonized.quantitySamples[0].sourceRevision.operatingSystem.patchVersion, 1) + XCTAssertEqual(decoded.harmonized.quantitySamples[0].harmonized.value, 123) + XCTAssertEqual(decoded.harmonized.quantitySamples[0].harmonized.unit, "mmHg") + XCTAssertEqual(decoded.harmonized.quantitySamples[0].harmonized.metadata, ["you": "saved it"]) + XCTAssertEqual(decoded.harmonized.quantitySamples[1].identifier, "HKQuantityTypeIdentifierBloodPressureDiastolic") + XCTAssertEqual(decoded.harmonized.quantitySamples[1].startTimestamp, 1626884800) + XCTAssertEqual(decoded.harmonized.quantitySamples[1].endTimestamp, 1626884800 + 60) + XCTAssertEqual(decoded.harmonized.quantitySamples[1].device?.name, "Guy's iPhone") + XCTAssertEqual(decoded.harmonized.quantitySamples[1].device?.manufacturer, "Guy") + XCTAssertEqual(decoded.harmonized.quantitySamples[1].device?.model, "6.1.1") + XCTAssertEqual(decoded.harmonized.quantitySamples[1].device?.hardwareVersion, "some_0") + XCTAssertEqual(decoded.harmonized.quantitySamples[1].device?.firmwareVersion, "some_1") + XCTAssertEqual(decoded.harmonized.quantitySamples[1].device?.softwareVersion, "some_2") + XCTAssertEqual(decoded.harmonized.quantitySamples[1].device?.localIdentifier, "some_3") + XCTAssertEqual(decoded.harmonized.quantitySamples[1].device?.udiDeviceIdentifier, "some_4") + XCTAssertEqual(decoded.harmonized.quantitySamples[1].sourceRevision.source.name, "mySource") + XCTAssertEqual(decoded.harmonized.quantitySamples[1].sourceRevision.source.bundleIdentifier, "com.kvs.hkreporter") + XCTAssertEqual(decoded.harmonized.quantitySamples[1].sourceRevision.version, "1.0.0") + XCTAssertEqual(decoded.harmonized.quantitySamples[1].sourceRevision.productType, "CocoaPod") + XCTAssertEqual(decoded.harmonized.quantitySamples[1].sourceRevision.systemVersion, "1.0.0.0") + XCTAssertEqual(decoded.harmonized.quantitySamples[1].sourceRevision.operatingSystem.majorVersion, 1) + XCTAssertEqual(decoded.harmonized.quantitySamples[1].sourceRevision.operatingSystem.minorVersion, 1) + XCTAssertEqual(decoded.harmonized.quantitySamples[1].sourceRevision.operatingSystem.patchVersion, 1) + XCTAssertEqual(decoded.harmonized.quantitySamples[1].harmonized.value, 83) + XCTAssertEqual(decoded.harmonized.quantitySamples[1].harmonized.unit, "mmHg") + XCTAssertEqual(decoded.harmonized.quantitySamples[1].harmonized.metadata, ["you": "saved it"]) + XCTAssertEqual(decoded.harmonized.categorySamples.count, 0) + XCTAssertEqual(decoded.harmonized.metadata, ["you": "saved it"]) + } + func testCreateFromDictionary() throws { + let dictionary: [String: Any] = [ + "device" : [ + "manufacturer" : "Guy", + "softwareVersion" : "some_2", + "model" : "6.1.1", + "localIdentifier" : "some_3", + "firmwareVersion" : "some_1", + "udiDeviceIdentifier" : "some_4", + "name" : "Guy's iPhone", + "hardwareVersion" : "some_0" + ], + "sourceRevision" : [ + "productType" : "CocoaPod", + "systemVersion" : "1.0.0.0", + "source" : [ + "name" : "mySource", + "bundleIdentifier" : "com.kvs.hkreporter" + ], + "operatingSystem" : [ + "majorVersion" : 1, + "minorVersion" : 1, + "patchVersion" : 1 + ], + "version" : "1.0.0" + ], + "uuid" : "BA0ADD39-638C-4FF8-AF48-0FC88CDCC48A", + "identifier" : "HKCorrelationTypeIdentifierBloodPressure", + "startTimestamp" : 1653657145.998812, + "endTimestamp" : 1653657205.998812, + "harmonized" : [ + "metadata" : [ + "you" : "saved it" + ], + "categorySamples" : [ + + ], + "quantitySamples" : [ + [ + "device" : [ + "manufacturer" : "Guy", + "softwareVersion" : "some_2", + "model" : "6.1.1", + "localIdentifier" : "some_3", + "firmwareVersion" : "some_1", + "udiDeviceIdentifier" : "some_4", + "name" : "Guy's iPhone", + "hardwareVersion" : "some_0" + ], + "sourceRevision" : [ + "productType" : "CocoaPod", + "systemVersion" : "1.0.0.0", + "source" : [ + "name" : "mySource", + "bundleIdentifier" : "com.kvs.hkreporter" + ], + "operatingSystem" : [ + "majorVersion" : 1, + "minorVersion" : 1, + "patchVersion" : 1 + ], + "version" : "1.0.0" + ], + "uuid" : "52DC2FFB-D361-4CDC-9450-29EFEBD1BD94", + "identifier" : "HKQuantityTypeIdentifierBloodPressureSystolic", + "startTimestamp" : 1653657145.998812, + "endTimestamp" : 1653657205.998812, + "harmonized" : [ + "value" : 123, + "metadata" : [ + "you" : "saved it" + ], + "unit" : "mmHg" + ] + ], + [ + "device" : [ + "manufacturer" : "Guy", + "softwareVersion" : "some_2", + "model" : "6.1.1", + "localIdentifier" : "some_3", + "firmwareVersion" : "some_1", + "udiDeviceIdentifier" : "some_4", + "name" : "Guy's iPhone", + "hardwareVersion" : "some_0" + ], + "sourceRevision" : [ + "productType" : "CocoaPod", + "systemVersion" : "1.0.0.0", + "source" : [ + "name" : "mySource", + "bundleIdentifier" : "com.kvs.hkreporter" + ], + "operatingSystem" : [ + "majorVersion" : 1, + "minorVersion" : 1, + "patchVersion" : 1 + ], + "version" : "1.0.0" + ], + "uuid" : "3850F06E-383B-476A-BFCC-4A6DF979CFAE", + "identifier" : "HKQuantityTypeIdentifierBloodPressureDiastolic", + "startTimestamp" : 1653657145.998812, + "endTimestamp" : 1653657205.998812, + "harmonized" : [ + "value" : 83, + "metadata" : [ + "you" : "saved it" + ], + "unit" : "mmHg" + ] + ] + ] + ] + ] + let epsilon = 1.0 + let sut = try Correlation.make(from: dictionary) + XCTAssertEqual(sut.identifier, "HKCorrelationTypeIdentifierBloodPressure") + XCTAssertEqual(sut.startTimestamp, 1653657145.998812, accuracy: epsilon) + XCTAssertEqual(sut.endTimestamp, 1653657205.998812, accuracy: epsilon) + XCTAssertEqual(sut.device?.name, "Guy's iPhone") + XCTAssertEqual(sut.device?.manufacturer, "Guy") + XCTAssertEqual(sut.device?.model, "6.1.1") + XCTAssertEqual(sut.device?.hardwareVersion, "some_0") + XCTAssertEqual(sut.device?.firmwareVersion, "some_1") + XCTAssertEqual(sut.device?.softwareVersion, "some_2") + XCTAssertEqual(sut.device?.localIdentifier, "some_3") + XCTAssertEqual(sut.device?.udiDeviceIdentifier, "some_4") + XCTAssertEqual(sut.sourceRevision.source.name, "mySource") + XCTAssertEqual(sut.sourceRevision.source.bundleIdentifier, "com.kvs.hkreporter") + XCTAssertEqual(sut.sourceRevision.version, "1.0.0") + XCTAssertEqual(sut.sourceRevision.productType, "CocoaPod") + XCTAssertEqual(sut.sourceRevision.systemVersion, "1.0.0.0") + XCTAssertEqual(sut.sourceRevision.operatingSystem.majorVersion, 1) + XCTAssertEqual(sut.sourceRevision.operatingSystem.minorVersion, 1) + XCTAssertEqual(sut.sourceRevision.operatingSystem.patchVersion, 1) + XCTAssertEqual(sut.harmonized.quantitySamples.count, 2) + XCTAssertEqual(sut.harmonized.quantitySamples[0].identifier, "HKQuantityTypeIdentifierBloodPressureSystolic") + XCTAssertEqual(sut.harmonized.quantitySamples[0].startTimestamp, 1653657145.998812, accuracy: epsilon) + XCTAssertEqual(sut.harmonized.quantitySamples[0].endTimestamp, 1653657205.998812, accuracy: epsilon) + XCTAssertEqual(sut.harmonized.quantitySamples[0].device?.name, "Guy's iPhone") + XCTAssertEqual(sut.harmonized.quantitySamples[0].device?.manufacturer, "Guy") + XCTAssertEqual(sut.harmonized.quantitySamples[0].device?.model, "6.1.1") + XCTAssertEqual(sut.harmonized.quantitySamples[0].device?.hardwareVersion, "some_0") + XCTAssertEqual(sut.harmonized.quantitySamples[0].device?.firmwareVersion, "some_1") + XCTAssertEqual(sut.harmonized.quantitySamples[0].device?.softwareVersion, "some_2") + XCTAssertEqual(sut.harmonized.quantitySamples[0].device?.localIdentifier, "some_3") + XCTAssertEqual(sut.harmonized.quantitySamples[0].device?.udiDeviceIdentifier, "some_4") + XCTAssertEqual(sut.harmonized.quantitySamples[0].sourceRevision.source.name, "mySource") + XCTAssertEqual(sut.harmonized.quantitySamples[0].sourceRevision.source.bundleIdentifier, "com.kvs.hkreporter") + XCTAssertEqual(sut.harmonized.quantitySamples[0].sourceRevision.version, "1.0.0") + XCTAssertEqual(sut.harmonized.quantitySamples[0].sourceRevision.productType, "CocoaPod") + XCTAssertEqual(sut.harmonized.quantitySamples[0].sourceRevision.systemVersion, "1.0.0.0") + XCTAssertEqual(sut.harmonized.quantitySamples[0].sourceRevision.operatingSystem.majorVersion, 1) + XCTAssertEqual(sut.harmonized.quantitySamples[0].sourceRevision.operatingSystem.minorVersion, 1) + XCTAssertEqual(sut.harmonized.quantitySamples[0].sourceRevision.operatingSystem.patchVersion, 1) + XCTAssertEqual(sut.harmonized.quantitySamples[0].harmonized.value, 123) + XCTAssertEqual(sut.harmonized.quantitySamples[0].harmonized.unit, "mmHg") + XCTAssertEqual(sut.harmonized.quantitySamples[0].harmonized.metadata, ["you": "saved it"]) + XCTAssertEqual(sut.harmonized.quantitySamples[1].identifier, "HKQuantityTypeIdentifierBloodPressureDiastolic") + XCTAssertEqual(sut.harmonized.quantitySamples[1].startTimestamp, 1653657145.998812, accuracy: epsilon) + XCTAssertEqual(sut.harmonized.quantitySamples[1].endTimestamp, 1653657205.998812, accuracy: epsilon) + XCTAssertEqual(sut.harmonized.quantitySamples[1].device?.name, "Guy's iPhone") + XCTAssertEqual(sut.harmonized.quantitySamples[1].device?.manufacturer, "Guy") + XCTAssertEqual(sut.harmonized.quantitySamples[1].device?.model, "6.1.1") + XCTAssertEqual(sut.harmonized.quantitySamples[1].device?.hardwareVersion, "some_0") + XCTAssertEqual(sut.harmonized.quantitySamples[1].device?.firmwareVersion, "some_1") + XCTAssertEqual(sut.harmonized.quantitySamples[1].device?.softwareVersion, "some_2") + XCTAssertEqual(sut.harmonized.quantitySamples[1].device?.localIdentifier, "some_3") + XCTAssertEqual(sut.harmonized.quantitySamples[1].device?.udiDeviceIdentifier, "some_4") + XCTAssertEqual(sut.harmonized.quantitySamples[1].sourceRevision.source.name, "mySource") + XCTAssertEqual(sut.harmonized.quantitySamples[1].sourceRevision.source.bundleIdentifier, "com.kvs.hkreporter") + XCTAssertEqual(sut.harmonized.quantitySamples[1].sourceRevision.version, "1.0.0") + XCTAssertEqual(sut.harmonized.quantitySamples[1].sourceRevision.productType, "CocoaPod") + XCTAssertEqual(sut.harmonized.quantitySamples[1].sourceRevision.systemVersion, "1.0.0.0") + XCTAssertEqual(sut.harmonized.quantitySamples[1].sourceRevision.operatingSystem.majorVersion, 1) + XCTAssertEqual(sut.harmonized.quantitySamples[1].sourceRevision.operatingSystem.minorVersion, 1) + XCTAssertEqual(sut.harmonized.quantitySamples[1].sourceRevision.operatingSystem.patchVersion, 1) + XCTAssertEqual(sut.harmonized.quantitySamples[1].harmonized.value, 83) + XCTAssertEqual(sut.harmonized.quantitySamples[1].harmonized.unit, "mmHg") + XCTAssertEqual(sut.harmonized.quantitySamples[1].harmonized.metadata, ["you": "saved it"]) + XCTAssertEqual(sut.harmonized.categorySamples.count, 0) + XCTAssertEqual(sut.harmonized.metadata, ["you": "saved it"]) + } } diff --git a/Tests/ElectrocardiogramTests.swift b/Tests/ElectrocardiogramTests.swift index 125977c..b02d38c 100644 --- a/Tests/ElectrocardiogramTests.swift +++ b/Tests/ElectrocardiogramTests.swift @@ -8,6 +8,184 @@ import XCTest import HealthKitReporter +@available(iOS 14.0, *) class ElectrocardiogramTests: XCTestCase { - + func testCreateFromDicitionary() throws { + let dictionary: [String: Any] = [ + "device" : [ + "softwareVersion" : "8.5.1", + "manufacturer" : "Apple Inc.", + "model" : "Watch", + "name" : "Apple Watch", + "hardwareVersion" : "Watch6,1" + ], + "sourceRevision" : [ + "productType" : "Watch6,1", + "systemVersion" : "8.5.1", + "source" : [ + "name" : "EKG", + "bundleIdentifier" : "com.apple.NanoHeartRhythm" + ], + "operatingSystem" : [ + "majorVersion" : 8, + "minorVersion" : 5, + "patchVersion" : 1 + ], + "version" : "1.90" + ], + "uuid" : "ECB16118-D47F-431C-BAC3-189FE8251FED", + "numberOfMeasurements" : 2, + "identifier" : "HKDataTypeIdentifierElectrocardiogram", + "endTimestamp" : 1650213492.810982, + "startTimestamp" : 1650213462.810982, + "harmonized" : [ + "voltageMeasurements" : [ + [ + "harmonized" : [ + "value" : 3.7860584259033203e-05, + "unit" : "V" + ], + "timeSinceSampleStart" : 0 + + ], + [ + "harmonized" : [ + "value" : 6.8293251037597656e-05, + "unit" : "V" + ], + "timeSinceSampleStart" : 0.175781250 + ] + ], + "averageHeartRate" : 61, + "classification" : "Sinus rhytm", + "samplingFrequencyUnit" : "Hz", + "count" : 2, + "averageHeartRateUnit" : "count/min", + "symptomsStatus" : "na", + "samplingFrequency" : 512, + "metadata" : [ + "HKMetadataKeyAppleECGAlgorithmVersion" : "2", + "HKMetadataKeySyncVersion" : "0", + "HKMetadataKeySyncIdentifier" : "47D89B1C-FC84-449A-91E1-FB6A2AA737D7" + ] + ] + ] + let epsilon = 1.0 + let sut = try Electrocardiogram.make(from: dictionary) + XCTAssertEqual(sut.identifier, "HKDataTypeIdentifierElectrocardiogram") + XCTAssertEqual(sut.startTimestamp, 1650213462.810982, accuracy: epsilon) + XCTAssertEqual(sut.endTimestamp, 1650213492.810982, accuracy: epsilon) + XCTAssertEqual(sut.numberOfMeasurements, 2) + XCTAssertEqual(sut.device?.name, "Apple Watch") + XCTAssertEqual(sut.device?.manufacturer, "Apple Inc.") + XCTAssertEqual(sut.device?.model, "Watch") + XCTAssertEqual(sut.device?.hardwareVersion, "Watch6,1") + XCTAssertEqual(sut.device?.softwareVersion, "8.5.1") + XCTAssertEqual(sut.sourceRevision.source.name, "EKG") + XCTAssertEqual(sut.sourceRevision.source.bundleIdentifier, "com.apple.NanoHeartRhythm") + XCTAssertEqual(sut.sourceRevision.version, "1.90") + XCTAssertEqual(sut.sourceRevision.productType, "Watch6,1") + XCTAssertEqual(sut.sourceRevision.systemVersion, "8.5.1") + XCTAssertEqual(sut.sourceRevision.operatingSystem.majorVersion, 8) + XCTAssertEqual(sut.sourceRevision.operatingSystem.minorVersion, 5) + XCTAssertEqual(sut.sourceRevision.operatingSystem.patchVersion, 1) + XCTAssertEqual(sut.harmonized.voltageMeasurements[0].harmonized.value, 3.7860584259033203e-05, accuracy: epsilon) + XCTAssertEqual(sut.harmonized.voltageMeasurements[0].harmonized.unit, "V") + XCTAssertEqual(sut.harmonized.voltageMeasurements[0].timeSinceSampleStart, 0) + XCTAssertEqual(sut.harmonized.voltageMeasurements[1].harmonized.value, 6.8293251037597656e-05, accuracy: epsilon) + XCTAssertEqual(sut.harmonized.voltageMeasurements[1].harmonized.unit, "V") + XCTAssertEqual(sut.harmonized.voltageMeasurements[1].timeSinceSampleStart, 0.175781250, accuracy: epsilon) + XCTAssertEqual(sut.harmonized.count, 2) + XCTAssertEqual(sut.harmonized.voltageMeasurements.count, 2) + XCTAssertEqual(sut.harmonized.averageHeartRate, 61) + XCTAssertEqual(sut.harmonized.classification, "Sinus rhytm") + XCTAssertEqual(sut.harmonized.samplingFrequencyUnit, "Hz") + XCTAssertEqual(sut.harmonized.averageHeartRateUnit, "count/min") + XCTAssertEqual(sut.harmonized.symptomsStatus, "na") + XCTAssertEqual(sut.harmonized.samplingFrequency, 512) + XCTAssertEqual( + sut.harmonized.metadata, [ + "HKMetadataKeyAppleECGAlgorithmVersion" : "2", + "HKMetadataKeySyncVersion" : "0", + "HKMetadataKeySyncIdentifier" : "47D89B1C-FC84-449A-91E1-FB6A2AA737D7" + ] + ) + } + func testCreateFromDicitionaryWithNoVoltageMeasurements() throws { + let dictionary: [String: Any] = [ + "device" : [ + "softwareVersion" : "8.5.1", + "manufacturer" : "Apple Inc.", + "model" : "Watch", + "name" : "Apple Watch", + "hardwareVersion" : "Watch6,1" + ], + "sourceRevision" : [ + "productType" : "Watch6,1", + "systemVersion" : "8.5.1", + "source" : [ + "name" : "EKG", + "bundleIdentifier" : "com.apple.NanoHeartRhythm" + ], + "operatingSystem" : [ + "majorVersion" : 8, + "minorVersion" : 5, + "patchVersion" : 1 + ], + "version" : "1.90" + ], + "uuid" : "ECB16118-D47F-431C-BAC3-189FE8251FED", + "numberOfMeasurements" : 15360, + "identifier" : "HKDataTypeIdentifierElectrocardiogram", + "endTimestamp" : 1650213492.810982, + "startTimestamp" : 1650213462.810982, + "harmonized" : [ + "averageHeartRate" : 61, + "classification" : "Sinus rhytm", + "samplingFrequencyUnit" : "Hz", + "count" : 2, + "averageHeartRateUnit" : "count/min", + "symptomsStatus" : "na", + "samplingFrequency" : 512, + "metadata" : [ + "HKMetadataKeyAppleECGAlgorithmVersion" : "2", + "HKMetadataKeySyncVersion" : "0", + "HKMetadataKeySyncIdentifier" : "47D89B1C-FC84-449A-91E1-FB6A2AA737D7" + ] + ] + ] + let epsilon = 1.0 + let sut = try Electrocardiogram.make(from: dictionary) + XCTAssertEqual(sut.identifier, "HKDataTypeIdentifierElectrocardiogram") + XCTAssertEqual(sut.startTimestamp, 1650213462.810982, accuracy: epsilon) + XCTAssertEqual(sut.endTimestamp, 1650213492.810982, accuracy: epsilon) + XCTAssertEqual(sut.device?.name, "Apple Watch") + XCTAssertEqual(sut.device?.manufacturer, "Apple Inc.") + XCTAssertEqual(sut.device?.model, "Watch") + XCTAssertEqual(sut.device?.hardwareVersion, "Watch6,1") + XCTAssertEqual(sut.device?.softwareVersion, "8.5.1") + XCTAssertEqual(sut.sourceRevision.source.name, "EKG") + XCTAssertEqual(sut.sourceRevision.source.bundleIdentifier, "com.apple.NanoHeartRhythm") + XCTAssertEqual(sut.sourceRevision.version, "1.90") + XCTAssertEqual(sut.sourceRevision.productType, "Watch6,1") + XCTAssertEqual(sut.sourceRevision.systemVersion, "8.5.1") + XCTAssertEqual(sut.sourceRevision.operatingSystem.majorVersion, 8) + XCTAssertEqual(sut.sourceRevision.operatingSystem.minorVersion, 5) + XCTAssertEqual(sut.sourceRevision.operatingSystem.patchVersion, 1) + XCTAssertEqual(sut.harmonized.voltageMeasurements.count, 0) + XCTAssertEqual(sut.harmonized.count, 2) + XCTAssertEqual(sut.harmonized.averageHeartRate, 61) + XCTAssertEqual(sut.harmonized.classification, "Sinus rhytm") + XCTAssertEqual(sut.harmonized.samplingFrequencyUnit, "Hz") + XCTAssertEqual(sut.harmonized.averageHeartRateUnit, "count/min") + XCTAssertEqual(sut.harmonized.symptomsStatus, "na") + XCTAssertEqual(sut.harmonized.samplingFrequency, 512) + XCTAssertEqual( + sut.harmonized.metadata, [ + "HKMetadataKeyAppleECGAlgorithmVersion" : "2", + "HKMetadataKeySyncVersion" : "0", + "HKMetadataKeySyncIdentifier" : "47D89B1C-FC84-449A-91E1-FB6A2AA737D7" + ] + ) + } } diff --git a/Tests/HealthKitReporterTests.swift b/Tests/HealthKitReporterTests.swift index 2851b2d..b07bd6a 100644 --- a/Tests/HealthKitReporterTests.swift +++ b/Tests/HealthKitReporterTests.swift @@ -12,15 +12,9 @@ class HealthKitReporterTests: XCTestCase { var healthKitReporter: HealthKitReporter! override func setUp() { - healthKitReporter = try! HealthKitReporter() + healthKitReporter = HealthKitReporter() } override func tearDown() { healthKitReporter = nil } - - func testDateToISO() { - let date = Date(timeIntervalSince1970: 1624906615) - let formatted = date.formatted(with: Date.iso8601) - XCTAssertEqual(formatted, "2021-06-28T20:56:55.000+02:00") - } } diff --git a/Tests/HeartbeatSeriesTests.swift b/Tests/HeartbeatSeriesTests.swift index 1d03d49..f19ffc8 100644 --- a/Tests/HeartbeatSeriesTests.swift +++ b/Tests/HeartbeatSeriesTests.swift @@ -8,6 +8,278 @@ import XCTest import HealthKitReporter +@available(iOS 13.0, *) class HeartbeatSeriesTests: XCTestCase { - + func testCreateFromDictionary() throws { + let dictionary: [String: Any] = [ + "device" : [ + "softwareVersion" : "8.0.1", + "manufacturer" : "Apple Inc.", + "model" : "Watch", + "name" : "Apple Watch", + "hardwareVersion" : "Watch6,1" + ], + "sourceRevision" : [ + "productType" : "Watch6,1", + "systemVersion" : "8.0.1", + "source" : [ + "name" : "Apple Watch von Victor", + "bundleIdentifier" : "com.apple.health.9482C212-CB6B-4949-A400-E448CCA82CEF" + ], + "operatingSystem" : [ + "majorVersion" : 8, + "minorVersion" : 0, + "patchVersion" : 1 + ], + "version" : "8.0.1" + ], + "uuid" : "061C93C9-95BD-476F-B170-3CDC504F7040", + "identifier" : "HKDataTypeIdentifierHeartbeatSeries", + "startTimestamp" : 1634151953.7457912, + "endTimestamp" : 1634152011.8551662, + "harmonized" : [ + "count" : 41, + "measurements" : [ + [ + "precededByGap" : true, + "done" : false, + "timeSinceSeriesStart" : 1.30859375 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 2.58203125 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 3.82421875 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 5.0234375 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 6.203125 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 7.47265625 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 8.63671875 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 9.84765625 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 11.140625 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 12.3125 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 13.5234375 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 14.7734375 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 15.94140625 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 17.15234375 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 18.4296875 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 19.578125 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 20.79296875 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 22.0546875 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 23.19140625 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 24.37890625 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 25.609375 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 26.72265625 + ], + [ + "precededByGap" : true, + "done" : false, + "timeSinceSeriesStart" : 31.265625 + ], + [ + "precededByGap" : true, + "done" : false, + "timeSinceSeriesStart" : 32.5 + ], + [ + "precededByGap" : true, + "done" : false, + "timeSinceSeriesStart" : 34.8984375 + ], + [ + "precededByGap" : true, + "done" : false, + "timeSinceSeriesStart" : 39.45703125 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 40.66015625 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 41.97265625 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 43.21484375 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 44.421875 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 45.703125 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 46.9140625 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 48.10546875 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 49.390625 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 50.55078125 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 51.75 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 53.07421875 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 54.265625 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 55.4140625 + ], + [ + "precededByGap" : false, + "done" : false, + "timeSinceSeriesStart" : 56.79296875 + ], + [ + "precededByGap" : false, + "done" : true, + "timeSinceSeriesStart" : 58.109375 + ] + ], + "metadata" : [ + "HKAlgorithmVersion" : "1" + ] + ] + ] + let epsilon = 1.0 + let sut = try HeartbeatSeries.make(from: dictionary) + XCTAssertEqual(sut.identifier, "HKDataTypeIdentifierHeartbeatSeries") + XCTAssertEqual(sut.startTimestamp, 1634151953.7457912, accuracy: epsilon) + XCTAssertEqual(sut.endTimestamp, 1634152011.8551662, accuracy: epsilon) + XCTAssertEqual(sut.device?.name, "Apple Watch") + XCTAssertEqual(sut.device?.manufacturer, "Apple Inc.") + XCTAssertEqual(sut.device?.model, "Watch") + XCTAssertEqual(sut.device?.hardwareVersion, "Watch6,1") + XCTAssertEqual(sut.device?.softwareVersion, "8.0.1") + XCTAssertEqual(sut.sourceRevision.source.name, "Apple Watch von Victor") + XCTAssertEqual(sut.sourceRevision.source.bundleIdentifier, "com.apple.health.9482C212-CB6B-4949-A400-E448CCA82CEF") + XCTAssertEqual(sut.sourceRevision.version, "8.0.1") + XCTAssertEqual(sut.sourceRevision.productType, "Watch6,1") + XCTAssertEqual(sut.sourceRevision.systemVersion, "8.0.1") + XCTAssertEqual(sut.sourceRevision.operatingSystem.majorVersion, 8) + XCTAssertEqual(sut.sourceRevision.operatingSystem.minorVersion, 0) + XCTAssertEqual(sut.sourceRevision.operatingSystem.patchVersion, 1) + XCTAssertEqual(sut.harmonized.count, 41) + XCTAssertEqual(sut.harmonized.measurements.count, 41) + XCTAssertEqual(sut.harmonized.measurements[0].precededByGap, true) + XCTAssertEqual(sut.harmonized.measurements[0].done, false) + XCTAssertEqual(sut.harmonized.measurements[0].timeSinceSeriesStart, 1.30859375) + XCTAssertEqual(sut.harmonized.measurements[1].precededByGap, false) + XCTAssertEqual(sut.harmonized.measurements[1].done, false) + XCTAssertEqual(sut.harmonized.measurements[1].timeSinceSeriesStart, 2.58203125) + XCTAssertEqual(sut.harmonized.measurements.last?.precededByGap, false) + XCTAssertEqual(sut.harmonized.measurements.last?.done, true) + XCTAssertEqual(sut.harmonized.measurements.last?.timeSinceSeriesStart, 58.109375) + XCTAssertEqual(sut.harmonized.metadata, ["HKAlgorithmVersion" : "1"]) + } } diff --git a/Tests/MetadataTests.swift b/Tests/MetadataTests.swift new file mode 100644 index 0000000..22fa89d --- /dev/null +++ b/Tests/MetadataTests.swift @@ -0,0 +1,31 @@ +// +// MetadataTests.swift +// +// +// Created by Victor Kachalov on 29.10.22. +// + +import XCTest +import HealthKitReporter + +class MetadataTests: XCTestCase { + func testMetadataString() { + let metadataExpressible: Metadata = ["HKWasUserEntered": "1"] + XCTAssertEqual(metadataExpressible, ["HKWasUserEntered": "1"]) + let metadataStringDictionary = Metadata.string(dictionary: ["HKWasUserEntered": "1"]) + XCTAssertEqual(metadataStringDictionary, ["HKWasUserEntered": "1"]) + } + func testMetadataDate() { + let date = Date() + let metadataExpressible: Metadata = ["HKWasUserEnteredOn": date] + XCTAssertEqual(metadataExpressible, ["HKWasUserEnteredOn": date]) + let metadataStringDictionary = Metadata.date(dictionary: ["HKWasUserEnteredOn": date]) + XCTAssertEqual(metadataStringDictionary, ["HKWasUserEnteredOn": date]) + } + func testMetadataDouble() { + let metadataExpressible: Metadata = ["HKWasUserEnteredValue": 10.0] + XCTAssertEqual(metadataExpressible, ["HKWasUserEnteredValue": 10.0]) + let metadataStringDictionary = Metadata.double(dictionary: ["HKWasUserEnteredValue": 10.0]) + XCTAssertEqual(metadataStringDictionary, ["HKWasUserEnteredValue": 10.0]) + } +} diff --git a/Tests/QuantityTests.swift b/Tests/QuantityTests.swift index 1b9c192..f131166 100644 --- a/Tests/QuantityTests.swift +++ b/Tests/QuantityTests.swift @@ -77,8 +77,8 @@ class QuantityTests: XCTestCase { func testCreateFromDictionary() throws { let dictionary: [String: Any] = [ "identifier": "HKQuantityTypeIdentifierStepCount", - "startTimestamp": 1624906509000.076, - "endTimestamp": 1624906569000.076, + "startTimestamp": 1624906509.076, + "endTimestamp": 1624906569.076, "device": [ "name": "FlutterTracker", "manufacturer": "kvs", diff --git a/Tests/WorkoutEventTests.swift b/Tests/WorkoutEventTests.swift index b1cae3a..7893074 100644 --- a/Tests/WorkoutEventTests.swift +++ b/Tests/WorkoutEventTests.swift @@ -35,8 +35,8 @@ class WorkoutEventTests: XCTestCase { } func testCreateFromDictionary() throws { let dictionary: [String: Any] = [ - "startTimestamp": 1624906675822, - "endTimestamp": 1624906675822, + "startTimestamp": 1624906675.822, + "endTimestamp": 1624906675.822, "duration": 0, "harmonized": [ "value": 6, diff --git a/Tests/WorkoutRouteTests.swift b/Tests/WorkoutRouteTests.swift index 99a471e..15ae747 100644 --- a/Tests/WorkoutRouteTests.swift +++ b/Tests/WorkoutRouteTests.swift @@ -8,6 +8,142 @@ import XCTest import HealthKitReporter +@available(iOS 11.0, *) class WorkoutRouteTests: XCTestCase { + func testCreateFromDicitionary() throws { + let dictionary: [String: Any] = [ + "device" : [ + "softwareVersion" : "8.5.1", + "manufacturer" : "Apple Inc.", + "model" : "Watch", + "name" : "Apple Watch", + "hardwareVersion" : "Watch6,1" + ], + "sourceRevision" : [ + "productType" : "Watch6,1", + "systemVersion" : "8.5.1", + "source" : [ + "name" : "Apple Watch von Victor", + "bundleIdentifier" : "com.apple.health.9482C212-CB6B-4949-A400-E448CCA82CEF" + ], + "operatingSystem" : [ + "majorVersion" : 8, + "minorVersion" : 5, + "patchVersion" : 1 + ], + "version" : "8.5.1" + ], + "uuid" : "15431FED-4009-4764-9B4F-9FDD64827335", + "identifier" : "HKWorkoutRouteTypeIdentifier", + "startTimestamp" : 1650106382.259656, + "endTimestamp" : 1650107789.9993167, + "harmonized" : [ + "count" : 2, + "metadata" : [ + "HKMetadataKeySyncVersion" : "2", + "HKMetadataKeySyncIdentifier" : "8DA1E494-C047-4610-967F-267D60BD6E16" + ], + "routes" : [ + [ + "locations" : [ + [ + "floor": 1, + "course" : 211.54032897949219, + "speed" : 0.124705970287323, + "longitude" : 13.354639734623429, + "horizontalAccuracy" : 2.3436229228973389, + "verticalAccuracy" : 1.3776830434799194, + "latitude" : 52.517285348919636, + "courseAccuracy" : 398.32894897460938, + "speedAccuracy" : 0.86697620153427124, + "altitude" : 36.923385620117188, + "timestamp" : 1650106382.259656, + ], + [ + "course" : 212.49124145507812, + "speed" : 0.14083768427371979, + "longitude" : 13.354638966592331, + "horizontalAccuracy" : 2.0688667297363281, + "verticalAccuracy" : 1.2691746950149536, + "latitude" : 52.517284600413831, + "courseAccuracy" : 290.92919921875, + "speedAccuracy" : 0.71512973308563232, + "altitude" : 36.95831298828125, + "timestamp" : 1650106382.9997792 + ], + ], + "done": false + ], + [ + "locations" : [ + [ + "course" : 181.96142578125, + "speed" : 4.3713326454162598, + "longitude" : 13.385890186794727, + "horizontalAccuracy" : 3.2566030025482178, + "verticalAccuracy" : 1.7064602375030518, + "latitude" : 52.48740014749324, + "courseAccuracy" : 6.4161453247070312, + "speedAccuracy" : 0.53145873546600342, + "altitude" : 46.786865234375, + "timestamp" : 1650107481.9998665 + ], + [ + "course" : 182.047607421875, + "speed" : 4.3631305694580078, + "longitude" : 13.385887939659334, + "horizontalAccuracy" : 3.2557823657989502, + "verticalAccuracy" : 1.7118692398071289, + "latitude" : 52.487360925517542, + "courseAccuracy" : 6.4148092269897461, + "speedAccuracy" : 0.53077465295791626, + "altitude" : 46.917694091796875, + "timestamp" : 1650107482.9998574 + ], + ], + "done": true + ] + ] + ] + ] + let epsilon = 1.0 + let sut = try WorkoutRoute.make(from: dictionary) + XCTAssertEqual(sut.identifier, "HKWorkoutRouteTypeIdentifier") + XCTAssertEqual(sut.startTimestamp, 1650106382.259656, accuracy: epsilon) + XCTAssertEqual(sut.endTimestamp, 1650107789.9993167, accuracy: epsilon) + XCTAssertEqual(sut.device?.name, "Apple Watch") + XCTAssertEqual(sut.device?.manufacturer, "Apple Inc.") + XCTAssertEqual(sut.device?.model, "Watch") + XCTAssertEqual(sut.device?.hardwareVersion, "Watch6,1") + XCTAssertEqual(sut.device?.softwareVersion, "8.5.1") + XCTAssertEqual(sut.sourceRevision.source.name, "Apple Watch von Victor") + XCTAssertEqual(sut.sourceRevision.source.bundleIdentifier, "com.apple.health.9482C212-CB6B-4949-A400-E448CCA82CEF") + XCTAssertEqual(sut.sourceRevision.version, "8.5.1") + XCTAssertEqual(sut.sourceRevision.productType, "Watch6,1") + XCTAssertEqual(sut.sourceRevision.systemVersion, "8.5.1") + XCTAssertEqual(sut.sourceRevision.operatingSystem.majorVersion, 8) + XCTAssertEqual(sut.sourceRevision.operatingSystem.minorVersion, 5) + XCTAssertEqual(sut.sourceRevision.operatingSystem.patchVersion, 1) + XCTAssertEqual(sut.harmonized.count, 2) + XCTAssertEqual(sut.harmonized.routes.count, 2) + XCTAssertEqual(sut.harmonized.routes[0].done, false) + XCTAssertEqual(sut.harmonized.routes[0].locations[0].course, 211.54032897949219, accuracy: epsilon) + XCTAssertEqual(sut.harmonized.routes[0].locations[0].speed, 0.124705970287323, accuracy: epsilon) + XCTAssertEqual(sut.harmonized.routes[0].locations[0].longitude, 13.354639734623429, accuracy: epsilon) + XCTAssertEqual(sut.harmonized.routes[0].locations[0].horizontalAccuracy, 2.3436229228973389, accuracy: epsilon) + XCTAssertEqual(sut.harmonized.routes[0].locations[0].verticalAccuracy, 1.3776830434799194, accuracy: epsilon) + XCTAssertEqual(sut.harmonized.routes[0].locations[0].latitude, 52.517285348919636, accuracy: epsilon) + XCTAssertEqual(sut.harmonized.routes[0].locations[0].courseAccuracy!, 398.32894897460938, accuracy: epsilon) + XCTAssertEqual(sut.harmonized.routes[0].locations[0].speedAccuracy!, 0.86697620153427124, accuracy: epsilon) + XCTAssertEqual(sut.harmonized.routes[0].locations[0].altitude, 36.923385620117188, accuracy: epsilon) + XCTAssertEqual(sut.harmonized.routes[0].locations[0].timestamp, 1650106382.259656, accuracy: epsilon) + XCTAssertEqual(sut.harmonized.routes[0].locations[0].floor, 1) + XCTAssertEqual( + sut.harmonized.metadata, [ + "HKMetadataKeySyncVersion" : "2", + "HKMetadataKeySyncIdentifier" : "8DA1E494-C047-4610-967F-267D60BD6E16" + ] + ) + } } diff --git a/Tests/WorkoutTests.swift b/Tests/WorkoutTests.swift index 291f370..2e9ae8a 100644 --- a/Tests/WorkoutTests.swift +++ b/Tests/WorkoutTests.swift @@ -10,7 +10,7 @@ import HealthKitReporter class WorkoutTests: XCTestCase { func testCreateThenEncodeThenDecode() throws { - let startDate = Date(timeIntervalSince1970: 16268848000) + let startDate = Date(timeIntervalSince1970: 1626884800) let endDate = startDate.addingTimeInterval(60) let sut = Workout( identifier: WorkoutType.workoutType.identifier!, @@ -73,8 +73,8 @@ class WorkoutTests: XCTestCase { from: encoded.data(using: .utf8)! ) XCTAssertEqual(decoded.identifier, "HKWorkoutTypeIdentifier") - XCTAssertEqual(decoded.startTimestamp, 16268848000) - XCTAssertEqual(decoded.endTimestamp, 16268848000 + 60) + XCTAssertEqual(decoded.startTimestamp, 1626884800) + XCTAssertEqual(decoded.endTimestamp, 1626884800 + 60) XCTAssertEqual(decoded.device?.name, "Guy's iPhone") XCTAssertEqual(decoded.device?.manufacturer, "Guy") XCTAssertEqual(decoded.device?.model, "6.1.1") @@ -92,8 +92,8 @@ class WorkoutTests: XCTestCase { XCTAssertEqual(decoded.sourceRevision.operatingSystem.minorVersion, 1) XCTAssertEqual(decoded.sourceRevision.operatingSystem.patchVersion, 1) XCTAssertEqual(decoded.duration, 10.0) - XCTAssertEqual(decoded.workoutEvents[0].startTimestamp, 16268848000) - XCTAssertEqual(decoded.workoutEvents[0].endTimestamp, 16268848000) + XCTAssertEqual(decoded.workoutEvents[0].startTimestamp, 1626884800) + XCTAssertEqual(decoded.workoutEvents[0].endTimestamp, 1626884800) XCTAssertEqual(decoded.workoutEvents[0].duration, 60.0) XCTAssertEqual(decoded.workoutEvents[0].harmonized.value, 6) XCTAssertEqual(decoded.workoutEvents[0].harmonized.description, "Paused") @@ -112,8 +112,8 @@ class WorkoutTests: XCTestCase { func testCreateFromDictionary() throws { let dictionary: [String: Any] = [ "identifier": "HKWorkoutTypeIdentifier", - "startTimestamp": 1624906615822, - "endTimestamp": 1624906675822, + "startTimestamp": 1624906615.822, + "endTimestamp": 1624906675.822, "device": [ "name": "FlutterTracker", "manufacturer": "kvs", @@ -142,8 +142,8 @@ class WorkoutTests: XCTestCase { "workoutEvents": [ [ "type": "Paused", - "startTimestamp": 1624906675822, - "endTimestamp": 1624906675822, + "startTimestamp": 1624906675.822, + "endTimestamp": 1624906675.822, "duration": 0, "harmonized": [ "value": 6,