Apple HealthKit is an SDK-based provider. Your iOS consumer app would embed the Vital Mobile SDKs on a supported stack. Data are then pulled from the Apple HealthKit data store on the user’s iOS device.

Refer to the Mobile SDK Installation and Vital Health SDK guides for SDK installation instructions and general API usage. This guide contains information on the the behaviour and required configuration specific to the Apple HealthKit integration.

Sync Frequency

App stateBehaviour
ForegroundApple HealthKit delivers any buffered and new changes immediately.
BackgroundHourly batch delivery of changes, subject to operating system throttling.

While the SDK schedules hourly data sync with Apple HealthKit, iOS has full discretion to defer the scheduled time based on factors like CPU usage, battery usage, connectivity, and Low Power Mode.

In other words, the Vital SDK — or any third-party HealthKit apps — cannot guarantee the sync to happen on a strict schedule. The hourly schedule is advisory and non-binding from the persective of iOS. The actual delivery frequency can therefore fluctuate from hourly, to once a day, or when certain opportunity arises (e.g., when Sleep Mode ends, or when the phone starts charging).

Background Delivery

The iOS SDK can support observing new HealthKit data even when your app is not actively being used by your app user. This provides a more seamless experience, since the app user need not periodically open your app to sync data.

1. Setup app entitlements

Enable the “HealthKit > Background Delivery” entitlement:

Enable the “Background Modes > Background Processing entitlement:

2. Update your Info.plist

In your “Info > Custom iOS Target Properties” section — also known as the Info.plist file — these entries should be configured:

KeyValue
Privacy - Health Share Usage Description
(NSHealthShareUsageDescription)
An explanation of your usage of the user’s HealthKit data.
Permitted background task scheduler identifiers
(BGTaskSchedulerPermittedIdentifiers)
Include io.tryvital.VitalHealthKit.ProcessingTask in the array, alongside any other BGTask identifiers of yours.

If you request write permissions, you must also specify:

KeyValue
Privacy - Health Update Usage Description
(NSHealthUpdateUsageDescription)
An explanation of what user health data your app is writing to Apple HealthKit.

3. Integrate with iOS system callbacks

You must call VitalHealthKitClient.automaticConfiguration() during application(_:didFinishLaunchingWithOptions:) of your UIKit UIApplicationDelegate. This applies to all iOS integrations, be it Native, React Native or Flutter.

This ensures that Vital has the opportunity to register all handlers before the app “finished launching” as per Apple HealthKit’s specific timing requirement. Background delivery may be missed if this timing requirement is not satisfied.

As per the documentation:

As soon as your app launches, HealthKit calls the update handler for any observer queries that match the newly saved data. If you plan on supporting background delivery, set up all your observer queries in your app delegate’s application(_:didFinishLaunchingWithOptions:) method. By setting up the queries in application(_:didFinishLaunchingWithOptions:), you ensure that you’ve instantiated your queries, and they’re ready to use before HealthKit delivers the updates.

In other words, make sure VitalHealthKitClient.automaticConfiguration() is called inside your UIKit App Delegate’s application(_:didFinishLaunchingWithOptions:) method.

For React Native and Flutter SDK consumers, this means you must configure this directly in native code (Swift / Objective-C). Typically, an App Delegate would have been already created as part of your generated React Native or Flutter Xcode project.

Your AppDelegate should then look like this:

Swift / Flutter iOS:

import VitalHealthKit

class AppDelegate: NSObject, UIApplicationDelegate {
  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {

    VitalHealthKitClient.automaticConfiguration()
    /// your code

    return true
  }
}

Objective-C / React Native iOS:

#import "AppDelegate.h"
#import "VitalHealthKitConfiguration.h"

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

  [VitalHealthKitConfiguration automaticConfiguration];
  /// your code

  return YES;
}

3. Epilogue

You are all set!

Note that there is no need to call syncData() manually at all. Once you have asked the user for permission on resources, sync would automatically starts every app launch, as well as whenever your app is woken up by Apple HealthKit to respond to newly available data.

As per the documentation:

HealthKit wakes your app whenever a process saves or deletes samples of the specified type. The system wakes your app at most once per time period defined by the specified frequency. Some sample types have a maximum frequency of HKUpdateFrequency.hourly. The system enforces this frequency transparently.

For example, on iOS, stepCount samples have an hourly maximum frequency.

This means that although we have background delivery’s frequency set to .hourly, we cannot guarantee hourly syncing on the dot.