Search code examples
iosswiftswiftuihealthkit

How can I get the Average Running Speed of the app user through HealthKit?


I am trying to create an app that gets all sorts of health data, and displays it in a neat format. This is just a personal practice project to learn about Healthkit, and I could find lots of information about how to get the step count and calories on YouTube, but nothing about how to find the running speed of the user. I look on the documentation, but the docs are scarce for healthkit, unless I'm using them incorrectly.

func fetchRunningStats(){
    let speed = HKQuantityType(.runningSpeed)
    let predicate = HKQuery.predicateForSamples(withStart: .startOfDay, end: Date())
    let query = HKStatisticsQuery(quantityType: speed, quantitySamplePredicate: predicate) 
    {
        _, result, error in guard
        let quantity = result, error == nil 
        else {
            print("error fetching running speed")
            return
        }
        let speedValue = quantity.averageQuantity()
        let activity = Activity(title: "Speed", subtitle: "Running Speed", image: "figure.run", amount: "\(speedValue)", id: 0)
            DispatchQueue.main.async {
                self.activities["averagespeed"] = activity
            }
            print(speedValue)
        }
    healthStore.execute(query)
}

This is the function to grab the average running speed, but it keeps returning a HKStatistic object, and I don't know how to "unwrap" it to get the value inside.


Solution

  • You have a couple of problems in your code.

    First, you need to specify the .discreteAverage option in your HKStatisticQuery otherwise the query will not return the averageValue you are looking for.

    Once you have the average value you can access it using doubleValue(for: HKUnit) - But, there is no intrinsic type for speed/velocity.

    You can create the required HKUnit using HKUnit.meter().unitDivided(by: HKUnit.second()) - ie m/s

    func fetchRunningStats(){
        let speed = HKQuantityType(.runningSpeed)
        let predicate = HKQuery.predicateForSamples(withStart: .startOfDay, end: Date())
        let query = HKStatisticsQuery(quantityType: speed, quantitySamplePredicate: predicate, options: [.discreteAverage]) 
        {
            _, result, error in guard
            let quantity = result, error == nil 
            else {
                print("error fetching running speed")
                return
            }
            let speedValue = quantity.averageQuantity()
            let activity = Activity(title: "Speed", subtitle: "Running Speed", image: "figure.run", amount: "\(speedValue)", id: 0)
    let speedQuantity = quantity.averageQuantity()
                
                let speedUnit = HKUnit.meter().unitDivided(by: HKUnit.second())
                
                if let speedValue = speedQuantity?.doubleValue(for: speedUnit) {
                    print("Average speed=\(speedValue) m/s")
                    DispatchQueue.main.async {
                        self.activities["averagespeed"] = activity
                    }
                }
            }
        healthStore.execute(query)
    }