'HealthKit data is not refreshed until I force close and open the app again

I'm trying to get the steps and distance walked from a concrete day to now, on an iOS app. Also, I need to refresh that data continuously, real-time like.

I tried two different ways of doing that, but both are returning always the same data until I force close and open the app again.

private func getDataSinceDate(startDate: Date, type: HKQuantityTypeIdentifier, success: @escaping (Double) -> Void, hkUnit: HKUnit, failure: @escaping (Error?)->()) {
        
        // type = .distanceWalkingRunning
        // hkUnit = HKUnit.meter()

        let quantityType = HKQuantityType.quantityType(forIdentifier: type)!
        let startDateDay = Calendar.current.startOfDay(for: startDate)
        
        let predicate = HKQuery.predicateForSamples(
            withStart: startDateDay,
            end: .now,
            options: .strictEndDate
        )
        
        let query = HKStatisticsQuery(
            quantityType: quantityType,
            quantitySamplePredicate: predicate,
            options: .cumulativeSum
        ) { _, result, error in
            
            if error != nil {
                failure(error)
                return
            }
            
            guard let result = result, let sum = result.sumQuantity() else {
                success(0)
                return
            }
            
            success(sum.doubleValue(for: hkUnit))
        }
        
        healthStore.execute(query)
    }

also tried

func getDistance(start: Date, end: Date, completion: ((Double)->())?) {

        let timePredicate = HKQuery.predicateForSamples(withStart: Calendar.current.startOfDay(for: start), end: end, options: .strictStartDate)

            let walkingCompound = NSCompoundPredicate(andPredicateWithSubpredicates:
            [timePredicate])

        let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: false)
        
        var sum : Double = 0.0
        
        let query = HKSampleQuery(sampleType: HKSampleType.quantityType(forIdentifier: .distanceWalkingRunning)!, predicate: walkingCompound, limit: 0, sortDescriptors: [sortDescriptor]) { (query, samples, error) in
            guard error == nil else {
                return
            }
            
            for case let inSample as HKQuantitySample in samples ?? [] {
                sum += inSample.quantity.doubleValue(for: HKUnit.meter())
            }
            
            completion?(sum)
        }
        
        healthStore.execute(query)
    }

Both with the same problem. They're not refreshing the data. I would like to get the steps / distance collected on HealthKit (steps/distance also on Apple Watch) but I don't want to do a Watch app because I don't want to depend on Apple Watch to do this, as there are many people using other smart bands.

Is there any way to have updated data every time I request it?



Solution 1:[1]

It seems like your end predicate is not refreshing to now each time you run your query. You can use nil as end to get all data since your starting date or double-check if your end is refreshing to now.

For getting real-time data, you can set a HKObserverQuery to get notified every time HealthKit gets new Steps data, and run your HKStatisticsQuery inside the ObserverQuery's handler.

Another option for you is using a HKStatisticsCollectionQuery instead of your HKStatisticsQuery, as in HKStatisticsCollectionQuery you can set an update handler that updates your statistics each time HK gets new data. https://developer.apple.com/documentation/healthkit/hkstatisticscollectionquery/1615723-statisticsupdatehandler

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 gggava