Exploring HealthKit: Activity Summary
Book

Exploring MusicKit and Apple Music API

Unlock the full power of MusicKit & Apple Music APIs in your apps with the best guide! Use code musickit-blog for a limited-time 35% discount!

Apple provides the class HKActivitySummary, which contains the move, exercise, and stand data for a given day. You can query the data using HKActivitySummaryQuery and, most recently, use HKActivitySummaryQueryDescriptor to get the sweet async/await syntax.

Permissions

The first thing is to make sure that you request authorization from the user to read the activity summary data:

let types = Set([HKObjectType.activitySummaryType()])

Date Range

After successful authorization, create a date range for fetching the activity summary. The example below fetches yesterday’s and the present day’s data:

let calendar = Calendar.autoupdatingCurrent
let yesterdayDate = calendar.date(byAdding: .day, value: -1, to: Date())

guard let yesterdayDate = yesterdayDate else { return }

var startComponents = calendar.dateComponents([.day, .month, .year], from: yesterdayDate)
startComponents.hour = 0
startComponents.minute = 0
startComponents.second = 0

var endComponents = startComponents
endComponents.day = 2 + (endComponents.day ?? 0)

Then, create a predicate for activity summaries between the two date components:

let predicate = HKQuery.predicate(forActivitySummariesBetweenStart: startComponents, end: endComponents)

Fetching the Data Using Closures

To initialize a new active summary query, you use the HKActivitySummaryQuery with the results handler providing an array of HKActivitySummary containing the activity summaries.

init(predicate: NSPredicate?, resultsHandler handler: @escaping (HKActivitySummaryQuery, [HKActivitySummary]?, Error?) -> Void)

The following example provides executing a query and printing the active energy burned and exercise minutes:

let query = HKActivitySummaryQuery(predicate: predicate) { (query, summaries, error) -> Void in
  guard let summaries else { return }

  for summary in summaries {
    let activeEnergyBurned = summary.activeEnergyBurned.doubleValue(for: HKUnit.kilocalorie())
    let exerciseMinutes = summary.appleExerciseTime.doubleValue(for: HKUnit.minute())
    let standHours = summary.appleStandHours.doubleValue(for: HKUnit.hour())

    debugPrint("activeEnergyBurned", activeEnergyBurned)
    debugPrint("exerciseMinutes", exerciseMinutes)
    debugPrint("standHours", standHours)
  }
}

Like forgetting to write resume() when working with network calls, DO NOT forget to call the store to execute the query after creating it:

var healthStore: HKHealthStore

store.execute(query)

Fetching the Data Using Modern Concurrency

With the latest async/await, HealthKit also got some upgrades; however, they are iOS 15.4+. After creating the predicate, you create a query descriptor:

let predicate = HKQuery.predicate(forActivitySummariesBetweenStart: startComponents, end: endComponents)

let activeSummaryDescriptor = HKActivitySummaryQueryDescriptor(predicate: predicate)

To get a snapshot of the activity summaries, you await the result, which is an array of activity summaries in the form of HKActivitySummary objects:

var healthStore: HKHealthStore

let summaries = try await activeSummaryDescriptor.result(for: store)

If you want to make sure that no data is lost while the query is running, you can have an asynchronous sequence emit the array of summaries:

let activeSummaryQueue = activeSummaryDescriptor.results(for: store)

activeSummaryTask = Task {
  for try await summaries in activeSummaryQueue {
    for summary in summaries {
      let activeEnergyBurned = summary.activeEnergyBurned.doubleValue(for: HKUnit.kilocalorie())
      let exerciseMinutes = summary.appleExerciseTime.doubleValue(for: HKUnit.minute())
      let standHours = summary.appleStandHours.doubleValue(for: HKUnit.hour())

      debugPrint("activeEnergyBurned", activeEnergyBurned)
      debugPrint("exerciseMinutes", exerciseMinutes)
      debugPrint("standHours", standHours)
    }
  }
}
Book

Exploring MusicKit and Apple Music API

Unlock the full power of MusicKit & Apple Music APIs in your apps with the best guide! Use code musickit-blog for a limited-time 35% discount!

Written by

Rudrank Riyam

Hi, my name is Rudrank. I create apps for Apple Platforms while listening to music all day and night. Author of "Exploring MusicKit". Apple WWDC 2019 scholarship winner.