0

I'm trying to get steps from half an hour ago and I'm using the method discussed here. The following is my code:

func getSteps(completion: @escaping (Double) -> Void) {
    let stepsQuantityType = HKQuantityType.quantityType(forIdentifier: .stepCount)!

    let now = Date()
    let calendar = Calendar.current
    let halfHourAgoDate = calendar.date(byAdding: .minute, value: -30, to: now)

    if let date = halfHourAgoDate {
        let predicate = HKQuery.predicateForSamples(withStart: date, end: now, options: .strictStartDate)

        let query = HKStatisticsQuery(quantityType: stepsQuantityType, quantitySamplePredicate: predicate, options: .cumulativeSum) { (_, result, error) in
            var resultCount = 0.0

            guard let result = result else {
                completion(resultCount)
                return
            }

            if let sum = result.sumQuantity() {
                resultCount = sum.doubleValue(for: HKUnit.count())
                return
            }

            DispatchQueue.main.async {
                completion(resultCount)
            }
        }

        healthStore.execute(query)

    } else {
        print("Error MainVC, date is being cast as nil")
    }
}

When I actually try to get steps, this is my code:

 var todaysSteps: Double = 0
 getSteps(completion: { (resultCount) -> Void in
                                todaysSteps = resultCount
                            })
 print(todaysSteps) // always comes out to 0.0

Yet whenever I run this code, the code returns 0.0. I've enabled HealthKit, and authorized it for steps, so I'm not sure what the reason is. Also note this is in my variable declarations:

let healthStore = HKHealthStore()
LFHS
  • 295
  • 1
  • 2
  • 15
  • Where are you checking the values? This is an asynchronous function, so the value is only valid inside the completion handler. – Dávid Pásztor Sep 13 '17 at 21:46
  • Basically, I'm setting the variable todaysSteps equal to my result count, and then comparing todaySteps to something else outside the completion handler. Yet it's always coming out to 0.0 – LFHS Sep 13 '17 at 21:47
  • Have a look into asynchronous programming. This is how it should work. If you really can't handle the value inside the completion handler, I can show you how to use DispatchGroups to access it only once it is actually available, but you still won't be able to use that value as if it was returned from a synchronous function. – Dávid Pásztor Sep 13 '17 at 22:00
  • If I understand your explanation, since this is function is asynchronous, I should do my conditional code inside, rather than outside the completion handler? – LFHS Sep 13 '17 at 22:11
  • Yes, that's exactly what you should do. – Dávid Pásztor Sep 13 '17 at 22:13
  • does this code work? I have issue on this line `if let sum = result.sumQuantity() {` `result.sumQuantity()` is nil every time – Matrosov Oleksandr Jan 15 '18 at 18:08

1 Answers1

1

For anyone encountering the same issue, you need to do the code inside the completion handler, so:

var todaysSteps: Double = 0
getSteps(completion: { (resultCount) -> Void in
                            print(resultCount)
})
LFHS
  • 295
  • 1
  • 2
  • 15