Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Query Property Wrappers, HealthChart, and Other Refactoring #27

Merged
merged 96 commits into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
9aaaa3a
[WIP] query property wrappers, concepts of a HealthChart
lukaskollmer Jan 12, 2025
d84d450
little cleanup
lukaskollmer Jan 12, 2025
af2254f
fix typo
lukaskollmer Jan 14, 2025
2fcf1b2
rework the HealthKit module itself a little bit
lukaskollmer Jan 14, 2025
335f426
small fixes, improve documentation
lukaskollmer Jan 14, 2025
9d6be14
centralise HealthKit auth handling, delay starting background observe…
lukaskollmer Jan 15, 2025
bea1710
make the config component configure function async, rework auth handl…
lukaskollmer Jan 15, 2025
4bb52de
RIP HealthKitTests (they were just checking the UserDefaults auth stu…
lukaskollmer Jan 15, 2025
cacfbe6
rename `__HKSampleTypeProviding` to `_HKSampleWithSampleType`
lukaskollmer Jan 16, 2025
fac771e
add HealthKit. isAuthorized, rename some parameters
lukaskollmer Jan 18, 2025
79e2e3d
merge SpeziHealthKitUI into SpeziHealthKit
lukaskollmer Jan 18, 2025
f8d16b4
enable "ExistentialAny" upcoming feature flag
lukaskollmer Jan 18, 2025
b642d79
rename HealthKitDataAccessRequirements → HealthKit.DataAccessRequirem…
lukaskollmer Jan 19, 2025
b47b1db
remove some things
lukaskollmer Jan 19, 2025
2cfdffe
remov
lukaskollmer Jan 19, 2025
80d3bbb
rename HealthKitSampleType → SampleType
lukaskollmer Jan 19, 2025
b246334
inline all the sample type getters
lukaskollmer Jan 19, 2025
edeed71
mark most of SampleType as @inlinable, localize sample type names and…
lukaskollmer Jan 19, 2025
ee4d321
try restore proper dependencies
lukaskollmer Jan 19, 2025
0ca7d74
add reference snapshots
lukaskollmer Jan 19, 2025
2b712de
add macOS support
lukaskollmer Jan 20, 2025
5f83cff
rework the "HealthKitDataSource" API
lukaskollmer Jan 20, 2025
2c0a599
split up the HealthChart into multiple files
lukaskollmer Jan 20, 2025
9e4e6b7
remove `frequency` parameter from `enableBackgroundDelivery` function
lukaskollmer Jan 20, 2025
6459e46
rework documentation (pt01)
lukaskollmer Jan 21, 2025
726c4ee
x
lukaskollmer Jan 21, 2025
3acef8a
remove InteractiveHealthChart
lukaskollmer Jan 21, 2025
3469baa
more documentation rework
lukaskollmer Jan 21, 2025
ab0e4ca
fix docc copyright notices
lukaskollmer Jan 21, 2025
8fab017
remove `withTimeRange` function
lukaskollmer Jan 21, 2025
e8ea0d0
HealthChart: remove errors overlay
lukaskollmer Jan 21, 2025
1aa6201
HealthChart: remove interactivity, swiftlint
lukaskollmer Jan 21, 2025
90ba660
rework HealthKitQueryTimeRange
lukaskollmer Jan 21, 2025
cb9fcf1
fix UITest dependencies
lukaskollmer Jan 21, 2025
d6aef67
adjust tests
lukaskollmer Jan 21, 2025
7dddd47
[Tests] force en_US locale
lukaskollmer Jan 21, 2025
264c1c7
HealthKitCharacteristicQuery : include usage example in docs
lukaskollmer Jan 21, 2025
2675017
bring DocC changes to readme
lukaskollmer Jan 21, 2025
e18f89c
vanity commit
lukaskollmer Jan 21, 2025
89c3407
UITests: enable swift 6 language mode
lukaskollmer Jan 22, 2025
d1341a5
[tests] always force use of en_US locale and time zone
lukaskollmer Jan 22, 2025
d9dabb8
rename `.anchorQuery` to `.continuous`
lukaskollmer Jan 22, 2025
3fc64ea
hmmm
lukaskollmer Jan 22, 2025
fb4df52
x
lukaskollmer Jan 22, 2025
494b62f
hmmm
lukaskollmer Jan 22, 2025
f5ad400
fix HealthKitQuery
lukaskollmer Jan 22, 2025
0621ef2
try to add some more tests
lukaskollmer Jan 22, 2025
1e6f32d
oof
lukaskollmer Jan 22, 2025
09eb23e
uwuuu
lukaskollmer Jan 22, 2025
282b12c
try to fix the test
lukaskollmer Jan 23, 2025
587b384
swiftlint
lukaskollmer Jan 23, 2025
b320564
my bad
lukaskollmer Jan 23, 2025
2a561b5
try to fix the test not being able to query app.staticTexts
lukaskollmer Jan 23, 2025
82357bd
license?
lukaskollmer Jan 23, 2025
268ae4c
license.
lukaskollmer Jan 23, 2025
5a8525e
include statistic query chart in UI tests; simplify SampleType and He…
lukaskollmer Jan 23, 2025
c322775
RequestReadAccess: add Info.plist notice
lukaskollmer Jan 23, 2025
81bc82f
de-generify the HealthChart
lukaskollmer Jan 23, 2025
9e318de
add `HealthKitQueryResults.isCurrentlyPerformingInitialFetch`
lukaskollmer Jan 23, 2025
8e0da6b
SampleType.heartRate: adjust expectedValuesRange
lukaskollmer Jan 23, 2025
81ded84
x
lukaskollmer Jan 23, 2025
a90c6bc
fix operator definition
lukaskollmer Jan 23, 2025
17a4b1d
test updates
lukaskollmer Jan 23, 2025
8796421
update XCTHealthKit dependency
lukaskollmer Jan 23, 2025
352ead0
Update SpeziHealthKitTests.swift
lukaskollmer Jan 23, 2025
093c8a4
rework CollectSample API
lukaskollmer Jan 24, 2025
3ca0c92
hmmm
lukaskollmer Jan 25, 2025
eb26de2
move HealthChart back into a separate UI target
lukaskollmer Jan 25, 2025
4b2e989
try to update docs
lukaskollmer Jan 25, 2025
14b6426
swiftlint
lukaskollmer Jan 25, 2025
b1a2cf6
remove stale localizations
lukaskollmer Jan 25, 2025
23ebe21
add well-known sample types
lukaskollmer Jan 25, 2025
f56fc66
codecov.yml licence
lukaskollmer Jan 25, 2025
8bf0d9b
add back the expectedValueRanges; fix tests
lukaskollmer Jan 25, 2025
3901f98
add missing licenses
lukaskollmer Jan 25, 2025
6e8e0bd
fix ui tests?
lukaskollmer Jan 25, 2025
b88bd4a
try to fix the test running
lukaskollmer Jan 25, 2025
3081291
try to fix ui tests
lukaskollmer Jan 25, 2025
bf3bef1
???
lukaskollmer Jan 25, 2025
3dcde39
codecov.yml
lukaskollmer Jan 25, 2025
3b82abb
codecov.yml
lukaskollmer Jan 25, 2025
60409a8
build-and-test.yml
lukaskollmer Jan 25, 2025
9fcd070
codecov.yml
lukaskollmer Jan 25, 2025
f5573cc
improve typing (use SampleType in more cases), improve tests
lukaskollmer Jan 25, 2025
b9d85f0
swiftlint
lukaskollmer Jan 25, 2025
541266c
add tests for HealthKitCharacteristic, rework it a little bit
lukaskollmer Jan 26, 2025
d82bfd7
try to fix ui tests
lukaskollmer Jan 26, 2025
390ecb6
try to fix ui tests
lukaskollmer Jan 26, 2025
6e75e9d
characteristic query tests
lukaskollmer Jan 27, 2025
463d289
try to fix ui tests
lukaskollmer Jan 27, 2025
e32a576
fix ui tests
lukaskollmer Jan 27, 2025
5c817ac
.spi.yml
lukaskollmer Jan 27, 2025
e9f513a
remove the remaining (now-unused) UserDefaults code
lukaskollmer Jan 27, 2025
cea84f0
update CollectSample docs to reflect new situation
lukaskollmer Jan 27, 2025
6a5d4d1
switch XCTHealthKit dependency
lukaskollmer Jan 27, 2025
f3d59b1
XCTHealthKit update
lukaskollmer Jan 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,24 @@ jobs:
name: Build and Test Swift Package
uses: StanfordSpezi/.github/.github/workflows/xcodebuild-or-fastlane.yml@v2
with:
artifactname: SpeziHealthKit.xcresult
runsonlabels: '["macOS", "self-hosted"]'
scheme: SpeziHealthKit
scheme: SpeziHealthKit-Package
artifactname: SpeziHealthKit-Package.xcresult
resultBundle: SpeziHealthKit-Package.xcresult
buildandtestuitests:
name: Build and Test UI Tests
uses: StanfordSpezi/.github/.github/workflows/xcodebuild-or-fastlane.yml@v2
with:
artifactname: TestApp.xcresult
runsonlabels: '["macOS", "self-hosted"]'
path: 'Tests/UITests'
scheme: TestApp
artifactname: TestApp.xcresult
resultBundle: TestApp.xcresult
uploadcoveragereport:
name: Upload Coverage Report
needs: [buildandtest, buildandtestuitests]
uses: StanfordSpezi/.github/.github/workflows/create-and-upload-coverage-report.yml@v2
with:
coveragereports: SpeziHealthKit.xcresult TestApp.xcresult
coveragereports: SpeziHealthKit-Package.xcresult TestApp.xcresult
secrets:
token: ${{ secrets.CODECOV_TOKEN }}
6 changes: 6 additions & 0 deletions .reuse/dep5
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/

Files: Tests/SpeziHealthKitTests/__Snapshots__/*
Copyright: 2025 Stanford University and the project authors (see CONTRIBUTORS.md)
License: MIT

1 change: 1 addition & 0 deletions .spi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ builder:
- platform: ios
documentation_targets:
- SpeziHealthKit
- SpeziHealthKitUI
1 change: 1 addition & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ SpeziHealthKit contributors

* [Paul Schmiedmayer](https://github.com/PSchmiedmayer)
* [Andreas Bauer](https://github.com/Supereg)
* [Lukas Kollmer](https://github.com/lukaskollmer)
lukaskollmer marked this conversation as resolved.
Show resolved Hide resolved
30 changes: 25 additions & 5 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,48 @@ let package = Package(
name: "SpeziHealthKit",
defaultLocalization: "en",
platforms: [
.iOS(.v17)
.iOS(.v17),
.macOS(.v14)
],
products: [
.library(name: "SpeziHealthKit", targets: ["SpeziHealthKit"])
.library(name: "SpeziHealthKit", targets: ["SpeziHealthKit"]),
.library(name: "SpeziHealthKitUI", targets: ["SpeziHealthKitUI"])
],
dependencies: [
.package(url: "https://github.com/StanfordSpezi/Spezi", from: "1.8.0")
.package(url: "https://github.com/StanfordSpezi/Spezi.git", from: "1.8.0"),
.package(url: "https://github.com/StanfordSpezi/SpeziFoundation.git", from: "2.1.0"),
.package(url: "https://github.com/StanfordSpezi/SpeziStorage.git", from: "1.2.2"),
.package(url: "https://github.com/pointfreeco/swift-snapshot-testing.git", from: "1.17.7")
] + swiftLintPackage(),
targets: [
.target(
name: "SpeziHealthKit",
dependencies: [
.product(name: "Spezi", package: "Spezi")
.product(name: "Spezi", package: "Spezi"),
.product(name: "SpeziFoundation", package: "SpeziFoundation"),
.product(name: "SpeziLocalStorage", package: "SpeziStorage")
],
swiftSettings: [.enableUpcomingFeature("ExistentialAny")],
plugins: [] + swiftLintPlugin()
),
.target(
name: "SpeziHealthKitUI",
dependencies: [
.target(name: "SpeziHealthKit"),
.product(name: "SpeziFoundation", package: "SpeziFoundation")
],
swiftSettings: [.enableUpcomingFeature("ExistentialAny")],
lukaskollmer marked this conversation as resolved.
Show resolved Hide resolved
plugins: [] + swiftLintPlugin()
),
.testTarget(
name: "SpeziHealthKitTests",
dependencies: [
.product(name: "XCTSpezi", package: "Spezi"),
.target(name: "SpeziHealthKit")
.target(name: "SpeziHealthKit"),
.target(name: "SpeziHealthKitUI"),
.product(name: "SnapshotTesting", package: "swift-snapshot-testing")
],
swiftSettings: [.enableUpcomingFeature("ExistentialAny")],
plugins: [] + swiftLintPlugin()
)
]
Expand Down
76 changes: 46 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FStanfordSpezi%2FSpeziHealthKit%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/StanfordSpezi/SpeziHealthKit)
[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FStanfordSpezi%2FSpeziHealthKit%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/StanfordSpezi/SpeziHealthKit)

Simplifies access to HealthKit samples ranging from single, anchored, and background queries.
Access Health data in your Spezi app.

## Overview

The Spezi HealthKit module simplifies access to HealthKit samples ranging from single, anchored, and background queries.
The Spezi HealthKit module enables apps to integrate with Apple's HealthKit system, fetch data, set up long-lived background data collection, and visualize Health-related data.

### Setup

Expand All @@ -29,12 +29,12 @@
[Swift package](https://developer.apple.com/documentation/xcode/creating-a-standalone-swift-package-with-xcode#Add-a-dependency-on-another-Swift-package).

> Important: If your application is not yet configured to use Spezi, follow the
[Spezi setup article](https://swiftpackageindex.com/stanfordspezi/spezi/documentation/spezi/initial-setup) and set up the core Spezi infrastructure.
[Spezi setup article](https://swiftpackageindex.com/stanfordspezi/spezi/documentation/spezi/initial-setup) and set up the core Spezi infrastructure.

### Example

Before you configure the ``HealthKit`` module, make sure your `Standard` in your Spezi Application conforms to the ``HealthKitConstraint`` protocol to receive HealthKit data.
The [`add(sample:)`](https://swiftpackageindex.com/stanfordspezi/spezihealthkit/documentation/spezihealthkit/healthkitconstraint/add(sample:)) function is triggered once for every newly collected HealthKit sample, and the [`remove(sample:)`](https://swiftpackageindex.com/stanfordspezi/spezihealthkit/documentation/spezihealthkit/healthkitconstraint/remove(sample:)) function
### Example: health data collection

Before you configure the ``HealthKit-class`` module, make sure your `Standard` in your Spezi Application conforms to the ``HealthKitConstraint`` protocol to receive HealthKit data. The ``HealthKitConstraint/add(sample:)`` function is triggered once for every newly collected HealthKit sample, and the ``HealthKitConstraint/remove(sample:)`` function is triggered once for every deleted HealthKit sample.
```swift
actor ExampleStandard: Standard, HealthKitConstraint {
// Add the newly collected HKSample to your application.
Expand All @@ -50,42 +50,58 @@
```


Then, you can configure the ``HealthKit`` module in the configuration section of your `SpeziAppDelegate`.
Then, you can configure the ``HealthKit-class`` module in the configuration section of your `SpeziAppDelegate`.
Provide ``HealthKitDataSourceDescription`` to define the data collection.
You can, e.g., use ``CollectSample`` to collect a wide variety of `HKSampleTypes`:
```swift
class ExampleAppDelegate: SpeziAppDelegate {
override var configuration: Configuration {
Configuration(standard: ExampleStandard()) {
if HKHealthStore.isHealthDataAvailable() {
HealthKit {
CollectSample(
HKQuantityType.electrocardiogramType(),
deliverySetting: .background(.manual)
)
CollectSample(
HKQuantityType(.stepCount),
deliverySetting: .background(.automatic)
)
CollectSample(
HKQuantityType(.pushCount),
deliverySetting: .anchorQuery(.manual)
)
CollectSample(
HKQuantityType(.activeEnergyBurned),
deliverySetting: .anchorQuery(.automatic)
)
CollectSample(
HKQuantityType(.restingHeartRate),
deliverySetting: .manual()
)
}
HealthKit {
CollectSample(.activeEnergyBurned)
CollectSample(.stepCount, start: .manual)
CollectSample(.pushCount, start: .manual)
CollectSample(.heartRate, continueInBackground: true)
CollectSample(.electrocardiogram, start: .manual)
RequestReadAccess(quantity: [.bloodOxygen])
}
}
}
}
```


### Example: querying Health data in SwiftUI

You can use [`SpeziHealthKitUI`](https://swiftpackageindex.com/stanfordspezi/spezihealthkit/documentation/spezihealthkitui)'s [`HealthKitQuery`](https://swiftpackageindex.com/stanfordspezi/spezihealthkit/documentation/spezihealthkitui/healthkitquery) and [`HealthKitStatisticsQuery`](https://swiftpackageindex.com/stanfordspezi/spezihealthkit/documentation/spezihealthkitui/healthkitstatisticsquery) property wrappers to access the Health database in a View:

Check failure on line 76 in README.md

View workflow job for this annotation

GitHub Actions / Linkspector

[linkspector] README.md#L76

Cannot reach https://swiftpackageindex.com/stanfordspezi/spezihealthkit/documentation/spezihealthkitui. Status: 404
Raw output
message:"Cannot reach https://swiftpackageindex.com/stanfordspezi/spezihealthkit/documentation/spezihealthkitui. Status: 404" location:{path:"README.md" range:{start:{line:76 column:13} end:{line:76 column:124}}} severity:ERROR source:{name:"linkspector" url:"https://github.com/UmbrellaDocs/linkspector"}

Check failure on line 76 in README.md

View workflow job for this annotation

GitHub Actions / Linkspector

[linkspector] README.md#L76

Cannot reach https://swiftpackageindex.com/stanfordspezi/spezihealthkit/documentation/spezihealthkitui/healthkitquery. Status: 404
Raw output
message:"Cannot reach https://swiftpackageindex.com/stanfordspezi/spezihealthkit/documentation/spezihealthkitui/healthkitquery. Status: 404" location:{path:"README.md" range:{start:{line:76 column:127} end:{line:76 column:251}}} severity:ERROR source:{name:"linkspector" url:"https://github.com/UmbrellaDocs/linkspector"}

Check failure on line 76 in README.md

View workflow job for this annotation

GitHub Actions / Linkspector

[linkspector] README.md#L76

Cannot reach https://swiftpackageindex.com/stanfordspezi/spezihealthkit/documentation/spezihealthkitui/healthkitstatisticsquery. Status: 404
Raw output
message:"Cannot reach https://swiftpackageindex.com/stanfordspezi/spezihealthkit/documentation/spezihealthkitui/healthkitstatisticsquery. Status: 404" location:{path:"README.md" range:{start:{line:76 column:256} end:{line:76 column:400}}} severity:ERROR source:{name:"linkspector" url:"https://github.com/UmbrellaDocs/linkspector"}
```swift
struct ExampleView: View {
@HealthKitQuery(.heartRate, timeRange: .today)
private var heartRateSamples

var body: some View {
ForEach(heartRateSamples) { sample in
// ...
}
}
}
```

Additionally, you can use [`SpeziHealthKitUI`](https://swiftpackageindex.com/stanfordspezi/spezihealthkit/documentation/spezihealthkitui)'s [`HealthChart`](https://swiftpackageindex.com/stanfordspezi/spezihealthkit/documentation/spezihealthkitui/healthchart) to visualise query results:

Check failure on line 90 in README.md

View workflow job for this annotation

GitHub Actions / Linkspector

[linkspector] README.md#L90

Cannot reach https://swiftpackageindex.com/stanfordspezi/spezihealthkit/documentation/spezihealthkitui. Status: 404
Raw output
message:"Cannot reach https://swiftpackageindex.com/stanfordspezi/spezihealthkit/documentation/spezihealthkitui. Status: 404" location:{path:"README.md" range:{start:{line:90 column:27} end:{line:90 column:138}}} severity:ERROR source:{name:"linkspector" url:"https://github.com/UmbrellaDocs/linkspector"}

Check failure on line 90 in README.md

View workflow job for this annotation

GitHub Actions / Linkspector

[linkspector] README.md#L90

Cannot reach https://swiftpackageindex.com/stanfordspezi/spezihealthkit/documentation/spezihealthkitui/healthchart. Status: 404
Raw output
message:"Cannot reach https://swiftpackageindex.com/stanfordspezi/spezihealthkit/documentation/spezihealthkitui/healthchart. Status: 404" location:{path:"README.md" range:{start:{line:90 column:141} end:{line:90 column:259}}} severity:ERROR source:{name:"linkspector" url:"https://github.com/UmbrellaDocs/linkspector"}
```swift
struct ExampleView: View {
@HealthKitQuery(.heartRate, timeRange: .today)
private var heartRateSamples

var body: some View {
HealthChart {
HealthChartEntry($heartRateSamples, drawingConfig: .init(mode: .line, color: .red))
}
}
}
```


For more information, please refer to the [API documentation](https://swiftpackageindex.com/StanfordSpezi/SpeziHealthKit/documentation).

## The Spezi Template Application
Expand Down
76 changes: 0 additions & 76 deletions Sources/SpeziHealthKit/CollectSample/CollectSample.swift

This file was deleted.

53 changes: 0 additions & 53 deletions Sources/SpeziHealthKit/CollectSample/CollectSamples.swift

This file was deleted.

Loading
Loading