How can I get the highest sample rate historical heart rate data from health store?

I am trying to get heart rate data from health store but when I make a query there are samples that come through with timestamps that shows that there are minutes that go by between the sample measurements. I remember watching an apple video where they were talking about the Quantity series and how these series have one kind of container for multiple data points of bpm data. I also see in the samples that there is a unit of " ___ counts per second" for each of the results so it would make sense if there were multiple datapoints within each of the results from the query but I don't know how to see what's inside of the results or if there is even anything more to them.

This is the code I am using to retrieve the data:

public func fetchLatestHeartRateSample(completion: @escaping (_ samples: [HKQuantitySample]?) -> Void) {

    /// Create sample type for the heart rate
    guard let sampleType = HKObjectType
      .quantityType(forIdentifier: .heartRate) else {
        completion(nil)
      return
    }

    /// Predicate for specifying start and end dates for the query
    let predicate = HKQuery
      .predicateForSamples(
        withStart: Date.distantPast,
        end: Date(),
        options: .strictEndDate)

    /// Set sorting by date.
    let sortDescriptor = NSSortDescriptor(
      key: HKSampleSortIdentifierStartDate,
      ascending: false)

    /// Create the query
    let query = HKSampleQuery(
      sampleType: sampleType,
      predicate: predicate,
      limit: Int(HKObjectQueryNoLimit),
      sortDescriptors: [sortDescriptor]) { ( _, results, error) in

      guard error == nil else {
        print("Error: \(error!.localizedDescription)")
        return
      }

      print(results ?? "Error printing results.")
    
      completion(results as? [HKQuantitySample])
    }
    
    healthStore.execute(query)
  }

Ultimately I want the most frequent heart rate data that is available. Ideally a bpm measurement every 5 - 10 seconds or less. Is this possible if I have not explicitly saved this heart rate data to the health store for a user before trying to access it or does Apple store all of this information in the health store regardless of the circumstances?

Any help is greatly appreciated!

Replies

Additional question ... When I make this query I only get data for 10 days. Even when I make a loop and do a query in each iteration, only 10 of those queries return data from the health store, the rest are just empty arrays. Does the health store only have a record for 10 days of data and the rest is deleted? Is there any way to get more than 10 days worth of data without storing the data in a database?

Ok, lots to unpack here. These are my observations:

  • Your query should return all available data within the time frame *
  • You can manually view the actual data available in the Apple Health app under the Browse Tab -> Heart -> Heart Rate -> Show All Data (At the Bottom)
  • I'm assuming that you're likely referring to Heart Rate data recorded by Apple Watch. In normal operating mode, Apple Watch will only generate a Heart Rate measurement every 4 - 5 minutes when the user is wearing their watch. If they start a workout, this increases to about 12 measurements per minute. This is where the HKQuantitySeriesSample comes in useful for efficiently querying this high intensity data
  • This code would allow you to access the first HR value from the sample you have run
if let result = results.first as? HKQuantitySample {
     print(result.quantity.doubleValue(for: HKUnit(from: "count/min")))
}
  • To answer your last original question, you can't read Health data that is not there. For Heart Rate, I think from what you're saying, you either need to generate and save data to the Health Store, or wait for the user to record it (presumably via Apple Watch) before trying to read it

*Right, going back to my original point and trying to answer your additional question. If you are querying the Health Store on iPhone, the Health Store data is only limited to what's actually saved in it, I'm not directly sure why you're only getting 10 days of data. That said, if its regular Heart Rate data the this is quite a big query, I'd recommend breaking it down into multiple queries and changing the predicate dates you have set. If you're querying on Apple Watch, you're only guaranteed to have access to the last 7 days of Health data.

Maybe you're looking at old enough data that's written to series. See the following for more info and how to access

https://developer.apple.com/documentation/healthkit/workouts_and_activity_rings/accessing_condensed_workout_samples