Skip to content

Commit

Permalink
Simplify metadata access
Browse files Browse the repository at this point in the history
  • Loading branch information
christophhagen committed Mar 19, 2024
1 parent bcc487f commit 8773d94
Show file tree
Hide file tree
Showing 13 changed files with 29 additions and 39 deletions.
8 changes: 5 additions & 3 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,12 @@ The library still provides a more convenient way to interact with metadata:

```swift
var metadata = Metadata() // typealias for [String : Any]
metadata[.menstrualCycleStart] = true // Sets HKMetadataKeyMenstrualCycleStart
let cycleStart: Bool = metadata[.menstrualCycleStart]
metadata.menstrualCycleStart = true // Sets HKMetadataKeyMenstrualCycleStart
let cycleStart: Bool = metadata.menstrualCycleStart
```

This shorthand format works for all known keys defined in the `HKMetadataKey` enum.

## Queries

Interacting with the `HKHealthStore` can be simplified by wrapping it in a `HealthStore`:
Expand Down Expand Up @@ -193,4 +195,4 @@ The function automatically queries for [condensed samples](https://developer.app
```swift
let route = try store.route(associatedWith: workout)
let locations = try store.locations(associatedWith: route!)
```
```
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ extension LowCardioFitnessEvent {
///
/// The VO2 Max value (in `ml/(kg·min)`)
public var vo2MaxValue: Double? {
metadata?.quantityValue(for: .vo2MaxValue, unit: Self.mlPerKgMin)
metadata?.vo2MaxValue?.doubleValue(for: Self.mlPerKgMin)
}

/// The threshold value used to calculate the Low cardio classification (in `ml/(kg·min)`).
Expand All @@ -59,14 +59,14 @@ extension LowCardioFitnessEvent {
/// A low-cardio fitness event indicates a period of time when the user’s VO2 max measurements consistently fall below the defined value.
/// The system triggers this event approximately once every four months.
public var fitnessThreshold: Double? {
metadata?.quantityValue(for: .lowCardioFitnessEventThreshold, unit: Self.mlPerKgMin)
metadata?.lowCardioFitnessEventThreshold?.doubleValue(for: Self.mlPerKgMin)
}

public init(value: HKCategoryValueLowCardioFitnessEvent, vo2MaxValue: Double, fitnessThreshold: Double, start: Date, end: Date, device: HKDevice? = nil, metadata: [String : Any]? = nil) {
let unit = Self.mlPerKgMin
var metadata = metadata ?? [:]
metadata[.vo2MaxValue] = HKQuantity(unit: unit, doubleValue: vo2MaxValue)
metadata[.lowCardioFitnessEventThreshold] = HKQuantity(unit: unit, doubleValue: fitnessThreshold)
metadata.vo2MaxValue = HKQuantity(unit: unit, doubleValue: vo2MaxValue)
metadata.lowCardioFitnessEventThreshold = HKQuantity(unit: unit, doubleValue: fitnessThreshold)
self.init(value: value, start: start, end: end, device: device, metadata: metadata)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ extension MenstrualFlow {

/// Indicates whether the sample represents the start of a menstrual cycle.
public var cycleStart: Bool? {
metadata?[.menstrualCycleStart]
metadata?.menstrualCycleStart
}

/**
Create a new Menstrual Flow sample.
*/
public init(value: HKCategoryValueMenstrualFlow, cycleStart: Bool, start: Date, end: Date, device: HKDevice? = nil, metadata: [String : Any]? = nil) {
var metadata = metadata ?? [:]
metadata[.menstrualCycleStart] = cycleStart
metadata.menstrualCycleStart = cycleStart
self.init(value: value, start: start, end: end, device: device, metadata: metadata)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ public struct SexualActivity: HKCategoryEmptySample {
Indicates if protection was used during sexual activity
*/
public var protectionUsed: Bool? {
metadata?[.sexualActivityProtectionUsed]
metadata?.sexualActivityProtectionUsed
}

public init(protectionUsed: Bool, start: Date, end: Date, device: HKDevice? = nil, metadata: [String : Any]? = nil) {
var metadata = metadata ?? [:]
metadata[.sexualActivityProtectionUsed] = protectionUsed
metadata.sexualActivityProtectionUsed = protectionUsed
self.init(start: start, end: end, device: device, metadata: metadata)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ public struct SleepAnalysis: HKCategoryEnumSample {
extension SleepAnalysis {

public var timeZone: TimeZone? {
guard let timeZoneString: String = metadata?[.timeZone] else {
guard let timeZoneString: String = metadata?.timeZone else {
return nil
}
return TimeZone(identifier: timeZoneString)
}

public init(value: HKCategoryValueSleepAnalysis, timeZone: TimeZone, start: Date, end: Date, device: HKDevice? = nil, metadata: [String : Any]? = nil) {
var metadata = metadata ?? [:]
metadata[.timeZone] = timeZone.identifier
metadata.timeZone = timeZone.identifier
self.init(value: value, start: start, end: end, device: device, metadata: metadata)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ extension BloodPressure {
}

public var foodType: String? {
metadata?[.foodType]
metadata?.foodType
}

/// The associated systolic blood pressure sample
Expand Down
4 changes: 2 additions & 2 deletions Sources/HealthKitExtensions/Correlations/Food.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ extension Food {

public init(foodType: String, dietaryEnergyConsumed: Double, start: Date, end: Date, nutritionSamples: [HKDietaryQuantity], uuid: UUID? = nil, device: HKDevice? = nil, metadata: [String : Any]? = nil) {
var metadata = metadata ?? [:]
metadata[.foodType] = foodType
metadata.foodType = foodType

var objects = Set(nutritionSamples.map { $0.sample })
let energyConsumed = DietaryEnergyConsumed(value: dietaryEnergyConsumed, start: start, end: end)
Expand All @@ -31,7 +31,7 @@ extension Food {
}

public var foodType: String? {
metadata?[.foodType]
metadata?.foodType
}

/// The associated sample of consumed dietary energy
Expand Down
4 changes: 2 additions & 2 deletions Sources/HealthKitExtensions/Metadata/Metadata+KnownKeys.swift
Original file line number Diff line number Diff line change
Expand Up @@ -421,8 +421,8 @@ extension Metadata {
- String value: `HKMetadataKeyHeartRateMotionContext`
- HealthKit Constant: ``HKMetadataKeyHeartRateMotionContext``
*/
public var heartRateMotionContext: HKHeartRateMotionContext? {
get { integerType(for: .heartRateMotionContext) }
public var heartRateMotionContext: HKHeartRateMotionContext {
get { integerType(for: .heartRateMotionContext) ?? .notSet }
set { set(int: newValue, for: .heartRateMotionContext) }
}

Expand Down
7 changes: 2 additions & 5 deletions Sources/HealthKitExtensions/Quantities/Heart/HeartRate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ extension HeartRate {

public init(countsPerSecond: Double, motionContext: HKHeartRateMotionContext, start: Date, end: Date, uuid: UUID? = nil, device: HKDevice? = nil, metadata: [String : Any]? = nil) {
var metadata = metadata ?? [:]
metadata[.heartRateMotionContext] = NSNumber(value: motionContext.rawValue)
metadata.heartRateMotionContext = motionContext
self.init(value: countsPerSecond, start: start, end: end, uuid: uuid, device: device, metadata: metadata)
}

Expand All @@ -67,9 +67,6 @@ extension HeartRate {
Treat these samples as if they used the ``HKHeartRateMotionContext.notSet`` motion context.
*/
public var motionContext: HKHeartRateMotionContext {
guard let number: NSNumber = metadata?[.heartRateMotionContext] else {
return .notSet
}
return .init(rawValue: number.intValue) ?? .notSet
metadata?.heartRateMotionContext ?? .notSet
}
}
9 changes: 3 additions & 6 deletions Sources/HealthKitExtensions/Quantities/Heart/Vo2Max.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,7 @@ extension Vo2Max {
The method used to calculate the user’s VO2 max rate.
*/
public var testType: HKVO2MaxTestType? {
guard let number: NSNumber = metadata?[.vO2MaxTestType] else {
return nil
}
return .init(rawValue: number.intValue)
metadata?.vO2MaxTestType
}

/**
Expand All @@ -69,7 +66,7 @@ extension Vo2Max {
*/
public init(value: Double, testType: HKVO2MaxTestType, start: Date, end: Date, device: HKDevice? = nil, metadata: [String : Any]? = nil) {
var metadata = metadata ?? [:]
metadata[.vO2MaxTestType] = NSNumber(value: testType.rawValue)
metadata.vO2MaxTestType = testType
self.init(value: value, start: start, end: end, device: device, metadata: metadata)
}

Expand All @@ -79,7 +76,7 @@ extension Vo2Max {
*/
public init(value: Double, testType: HKVO2MaxTestType, start: Date, end: Date, uuid: UUID, device: HKDevice? = nil, metadata: [String : Any]? = nil) {
var metadata = metadata ?? [:]
metadata[.vO2MaxTestType] = NSNumber(value: testType.rawValue)
metadata.vO2MaxTestType = testType
self.init(value: value, start: start, end: end, uuid: uuid, device: device, metadata: metadata)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ extension SixMinuteWalkTestDistance {
The key is read-only.
*/
public var appleDeviceCalibrated: Bool? {
metadata?[.appleDeviceCalibrated]
metadata?.appleDeviceCalibrated
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,6 @@ extension WalkingAsymmetryPercentage {
Indicates the placement of the device that measured a sample.
*/
var devicePlacementSide: HKDevicePlacementSide? {
guard let number: NSNumber = metadata?[.devicePlacementSide] else {
return nil
}
return .init(rawValue: number.intValue)
metadata?.devicePlacementSide
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,12 @@ extension InsulinDelivery {

/// The medical reason for administering insulin.
var reason: HKInsulinDeliveryReason? {
guard let value: NSNumber = metadata?[.insulinDeliveryReason] else {
return nil
}
return .init(rawValue: value.intValue)
metadata?.insulinDeliveryReason
}

public init(amount: Double, reason: HKInsulinDeliveryReason, start: Date, end: Date, uuid: UUID? = nil, device: HKDevice? = nil, metadata: [String : Any]? = nil) {
var metadata = metadata ?? [:]
metadata[.insulinDeliveryReason] = NSNumber(value: reason.rawValue)
metadata.insulinDeliveryReason = reason
self.init(value: amount, start: start, end: end, uuid: uuid, device: device, metadata: metadata)
}
}

0 comments on commit 8773d94

Please sign in to comment.