Streaming is available in most browsers,
and in the Developer app.
-
Get started with HealthKit in visionOS
Discover how to use HealthKit to create experiences that take full advantage of the spatial canvas. Learn the capabilities of HealthKit on the platform, find out how to bring an existing iPadOS app to visionOS, and explore the special considerations governing HealthKit during a Guest User session. You'll also learn ways to use SwiftUI, Swift Charts, and Swift concurrency to craft innovative experiences with HealthKit.
Chapters
- 0:00 - Introduction
- 1:52 - HealthKit in visionOS
- 3:48 - Spatial health experiences
- 7:47 - Guest User support
Resources
- Bringing multiple windows to your SwiftUI app
- Forum: Health & Fitness
- HealthKit
- Let others use your Apple Vision Pro
- Visualizing HealthKit State of Mind in visionOS
Related Videos
WWDC24
WWDC23
WWDC20
-
Download
Hello, and welcome. My name is Zach. And I'm Sirinda. We’re engineers working on visionOS Health experiences.
As you might know, HealthKit provides a centralized and encrypted repository for the user’s health data, and with permission, you can access this data to create experiences that help people get healthy and stay healthy.
HealthKit capabilities include the ability to query and write health data, as well as aggregate and compute statistics of data over time.
You can also register your app to receive updates in the foreground or background when data changes.
Data can be stored in HealthKit across a broad spectrum of health domains, including activity, heart, and sleep, as well as clinical health records such as immunizations and procedures.
For more information on HealthKit, refer to our 2020 session, "Getting Started with HealthKit".
Last year, we brought HealthKit to a new platform with the release of iPadOS 17, which enabled you to create rich experiences that draw upon data stored in HealthKit to explore on iPad, like this app, Rise.
That’s right! And now, with visionOS 2, HealthKit is available on Apple Vision Pro. Spatial computing unlocks exciting opportunities to build a wide range of immersive and collaborative Health experiences.
We’re excited to show you how easy it is to build a HealthKit-powered app for visionOS. In this presentation, we’ll go over the capabilities of HealthKit in visionOS. Then, we’ll demonstrate some ways to craft experiences that feel at home within the Shared Space.
Finally, we’ll discuss the Guest User feature of visionOS and how HealthKit operates for Guest Users. Let’s begin by taking a look at the capabilities of the framework on the new platform.
HealthKit in visionOS behaves very similarly as in iPadOS. Your app can read and write data, compute statistics, as well as register for updates. Here are a couple other things to keep in mind.
As on other platforms, the user can view and edit each app’s authorization to health data in the Settings app.
And users can have their data sync between their devices periodically through iCloud.
HealthKit in visionOS is available for apps using the visionOS SDK and iPadOS apps compiled against iOS 17 or later.
For today’s session, we’ve been working on an app that lets you log emotions corresponding to calendar events using the new HealthKit state of mind API, and I want to bring this app to visionOS. To learn more about how we’re using the state of mind API, check out this year’s session, "Explore wellbeing APIs in HealthKit".
Let’s review the basics. When adopting HealthKit, it’s essential for your app to check whether health data is available, which can vary based on factors such as device and OS version.
Use the function isHealthDataAvailable to adjust your app’s experience appropriately if you want to continue supporting previous versions of visionOS.
After checking whether health data is available, you must next request authorization from the user to read or write the data types your app is interested in.
The healthDataAccessRequest function will trigger a prompt for the user to grant your app access to health data. It’s best to request only what you need and only at the moment your app needs it.
Following these best practices makes it really easy to update an iPadOS app to run on visionOS. In fact, you don’t need to do anything! Since my app is checking for health data availability using the APIs I outlined, when I compile it against iOS 17 or later, the app already offers a Designed for iPad experience on visionOS 2.0, with no updates needed. This puts me at an excellent starting point. Now, I’ll hand it off to Sirinda to walk through some best practices to consider if you’re interested in developing a HealthKit app that leans in to spatial computing.
Thanks, Zach. I’d like to show how easy it is to design our app for visionOS.
First, I’ll make sure that our app adopts the design and interaction patterns of visionOS, so that it takes advantage of the strengths of the platform.
I’ll also look for opportunities to refine and enhance our experience to surface more information and add nuance to the health data we display.
I’ll then take a moment to get inspired by ways to go above and beyond to really make HealthKit experiences shine on visionOS.
Let’s begin.
First, I’ll add visionOS as a destination to our app target, which will enable running our app on the platform.
Choosing Designed for iPad will get you the experience that Zach demoed. For today, I’ll choose Apple Vision to fully utilize the visionOS SDK.
Our app will use the same HealthKit data authorization configurations as iPadOS. It just works! For more information on bringing your existing apps to visionOS, check out the session "Elevate your windowed app for spatial computing".
Alright! Now that I've built our app for visionOS, it automatically adopts the standard system appearance. Standard SwiftUI components like TabView and Sheets translate beautifully to visionOS.
Since health data syncs across devices, we can now view the same charts and insights on Apple Vision Pro. And because our insights are configured using Swift Charts, they already look great.
Now that our app looks right at home on the platform, let’s explore how we can make use of this infinite spatial canvas. I’ve already made a couple of changes that enhance the experience on visionOS.
In this tab, I’ve made the chart dynamically resizable so that when I pinch and drag to expand the app window, I can see even more data at a glance.
To do this, I’m using a new SwiftUI API this year, onGeometryChange, to observe for changes in our chart’s size. I can scale up the number of chart points in response to a larger view.
And since I still have room to spare in our spatial canvas, why not compare two charts, side-by-side? Thankfully, adding multi-window support is easy, because my iPad app already supports split view. To learn more about how to configure multi-window support, see the documentation linked in our session notes.
Here in my code, I create a Button that calls the openWindow action with an identifier corresponding to the new chart. The action opens up a chart in a new window. And we don’t have to stop there! It’s easy to create fully immersive spatial experiences without having to rewrite your entire app.
For example, I’d like to reimagine our emotion logging experience to take advantage of the immersive capabilities of visionOS.
Let’s say I just wrapped up a brainstorm session, and I want to reflect on how I’m feeling.
On Apple Vision Pro, I can enter an immersive space.
Other apps are hidden, and the surrounding passthrough dims to provide a sense of separation from my workspace.
With no distractions in the way, I’ll reflect on my latest calendar event through a colorful immersive experience.
Once I tap Save to HealthKit, the color fades from the passthrough and my apps return, so I can continue right where I left off. With all these updates, our app feels at home on visionOS, we’ve enhanced existing experiences, and even created some new ones. Nice. Now that your app has been customized for visionOS, there’s one more thing you need to do, and that has to do with Guest User.
Guest User is a feature of visionOS that allows others to set up and try out Apple Vision Pro. It’s a great way to experience spatial computing, and it includes features to preserve the owner’s data and privacy. For a more detailed overview of Guest User, check out the article "Let others use your Apple Vision Pro" from Apple Support.
During a Guest User session, the Guest is able to use apps that the owner has authorized. In most cases, the experience is unchanged, but there are some special considerations when working with HealthKit. Apps running for the guest can still access HealthKit data if they are already authorized. However, apps cannot request additional HealthKit authorizations from the guest, and the system will not present the authorization flow if requested, returning an error instead.
The Guest is also not able to edit authorization, privacy, or security options in visionOS Settings.
There’s one more restriction on interacting with health data as a Guest User, and that’s when it comes to writing data.
Health data cannot be written to HealthKit during a Guest User session. This is to prevent data generated by the guest from mixing with the owner’s health data.
HealthKit will return a new error if an app attempts to write data during the session. Handling this error gives you the opportunity to safely discard data generated by the Guest, which ensures that it isn’t saved to the owner’s health store at a later time. This is also a good place to trigger an alert to indicate to Guests that the data has not been saved.
Thanks for the run-down on Guest User. Let’s update our app with these considerations in mind.
As Zach mentioned, authorization sheets are not presented to Guest Users. That means that any call to healthDataAccessRequest during a Guest User session will fail with an error. We recommend deferring requests for a later time. A Guest User may also attempt to write data. However, the sample will fail to save to the health store, so I’ve updated the existing logic to handle the error I receive.
As Zach said, when receiving this error, we recommend discarding health data samples generated by the guest. Finally, we want to notify the Guest User that their data has not been saved. This is the code that enables the user to choose an emotion. Here, I’ve modified this button to present an alert any time an error is thrown when a guest tries to log an emotion. Now that we've configured our app for a seamless Guest User experience, let’s make sure that our changes work as intended. When I open the app as a Guest User, I will not see any health data authorization prompts. This is because apps running for Guests inherit authorizations given by the owner. So, I’m able to experience the app as the owner would. However, let’s try to log an emotion.
I’ll tap this event, and make a selection.
Once I’m done, an alert is presented to notify me that my data as a Guest User has not been saved. Handling the error in this way allows guests to get a feel for the app, without adding their data to the owner’s health store.
Now that I’ve configured our app to handle Guest Users, I’m just about ready to share my app in Apple Vision Pro with friends and family. Here are some best practices to keep in mind: Guest Users are restricted from authorizing health data access, so make sure to update your authorization calls to handle this error appropriately.
Remember to discard any health data that the Guest User has attempted to write. This helps to prevent data generated by the Guest from mixing with the owner’s health data.
Finally, remember that apps can continue to read health data if the owner has already authorized the app.
Sticking to these best practices is vital to maintaining a seamless experience for both the Guest User and the owner! Thanks Sirinda, awesome work. To summarize, HealthKit is coming to visionOS, enabling reading, writing, and observing of health data on a new platform.
When adopting, take the opportunity to refine and rethink your experiences for spatial computing.
And remember to adjust your code in light of how HealthKit operates for Guest Users.
For more information, you can check out these talks, and be sure to download our sample app to see some examples in code. We’re really excited to be bringing HealthKit to visionOS, and look forward to seeing the experiences you’ll build. Thanks for joining us!
-
-
2:43 - Check whether health data is available
import HealthKit if HKHealthStore.isHealthDataAvailable() { // Configure HealthKit-powered experiences } else { // Omit HealthKit experiences }
-
3:03 - Request authorization to read or write data
import HealthKitUI import SwiftUI func healthDataAccessRequest( store: HKHealthStore, shareTypes: Set<HKSampleType>, readTypes: Set<HKObjectType>? = nil, trigger: some Equatable, completion: @escaping (Result<Bool, any Error>) -> Void ) -> some View
-
5:59 - Update number of chart points based on chart’s size
// Update number of chart points based on chart’s size import SwiftUI import HealthKit import Charts struct ChartView: View { @State var chartBinCount: Int var body: some View { Chart { ... // Chart body } .onGeometryChange(for: Int.self) { proxy in // Observe for changes to the chart’s size Int(proxy.size.width / 80) // 80 points per chart point } action: { newValue in // Update the number of chart points chartBinCount = newValue } } }
-
6:33 - Open chart as a new window
// Opens chart as a new window struct NewChartViewerButton: View { @Environment(\.openWindow) private var openWindow var body: some View { Button("Open In New Window", systemImage: "plus.rectangle.on.rectangle") { openWindow(id: "chart-viewer-window") } } }
-
9:00 - HealthKit returns a new error if a write is attempted during a Guest User session
let sample = HKStateOfMind(date: date, kind: .momentaryEmotion, valence: valence, labels: [label], associations: [association]) do { try await healthStore.save(sample) } catch { switch error { case HKError.errorNotPermissibleForGuestUserMode: // Drop data generated in a Guest User session default: // Existing error handling } }
-
9:26 - Request authorization to State of Mind datatype
// Request authorization to State of Mind datatype @main struct HKStateOfMindDataSampleApp: App { @State var toggleHealthDataAuthorization = false @State var healthDataAuthorized: Bool? var body: some Scene { WindowGroup { TabView { ... } .healthDataAccessRequest(store: healthStore, shareTypes: [.stateOfMindType()], readTypes: [.stateOfMindType()], trigger: toggleHealthDataAuthorization) { result in switch result { case .success: healthDataAuthorized = true case .failure(let error as HKError): switch (error.code) { case .errorNotPermissibleForGuestUserMode: // Defer requests for a later time default: // Existing error handling } ... } } } } }
-
9:42 - Save a State of Mind sample from an emoji type
// Saves a State of Mind sample from an emoji type public func saveSample(date: Date, association: HKStateOfMind.Association, healthStore: HKHealthStore, didError: Binding<Bool>) async -> SaveDetails? { do { let sample = createSample(date: date, association: association) try await healthStore.save(sample) } catch { switch error { case HKError.errorNotPermissibleForGuestUserMode: // Drop data you generate in a Guest User session. didError.wrappedValue = true return SaveDetails(errorString: "Health data is not saved for Guest Users.") default: // Existing error handling. didError.wrappedValue = true return SaveDetails(errorString: "Health data could not be saved: \(error)") } } ...
-
9:58 - Present an alert with a message using the given details
// Present an alert with a message using the given details struct EventView: View { @State private var showAlert: Bool = false @State private var saveDetails: EmojiType.SaveDetails? = nil var body: some View { EmojiPicker() .alert("Unable to Save Health Data", isPresented: $showAlert, presenting: saveDetails, actions: { _ in }, // default OK button message: { details in Text(details.errorString) }) } }
-
-
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.