完成处理程序在任务完成之前返回

时间:2020-08-04 23:12:05

标签: swift healthkit completionhandler

我有一个函数,该函数具有一个完成处理程序,该处理程序将在任务完成后返回,但是从我得到的输出中,它表明完成处理程序被视为已完成,并在任务完成之前返回了。 / p>

函数被调用:

private func getSteps(completion: (Int) -> ()) {
    var val: Int = 0
    guard let sampleType = HKObjectType.quantityType(forIdentifier: .stepCount) else { return }
    let startDate = Calendar.current.startOfDay(for: Date())
    let predicate = HKQuery.predicateForSamples(withStart: startDate, end: Date(), options: .strictEndDate)
    var interval = DateComponents()
    
    interval.day = 1
    let query = HKStatisticsCollectionQuery(quantityType: sampleType, quantitySamplePredicate: predicate, options: [.cumulativeSum], anchorDate: startDate, intervalComponents: interval)
    query.initialResultsHandler = { query,result,error in
        if let myresult = result {
            myresult.enumerateStatistics(from: startDate, to: Date()) { (statistic, value) in
                if let count = statistic.sumQuantity() {
                    val = Int(count.doubleValue(for: HKUnit.count()))
                }
            }
        }
    }
    healthStore.execute(query)
    completion(val)
}

当我打印函数的完成处理程序时,它将打印0而不是Int(count.doubleValue(for: HKUnit.count())),该val设置为函数内部。对于为什么我得到0而不是set val的任何输入,将不胜感激!

1 个答案:

答案 0 :(得分:3)

请注意,query.initialResultsHandler异步,您的代码将按以下顺序执行:

private func getSteps(completion: (Int) -> ()) {
    // #1
    var val: Int = 0
    ...
    // #2
    query.initialResultsHandler = { query,result,error in
        // #5
        if let myresult = result {
            myresult.enumerateStatistics(from: startDate, to: Date()) { (statistic, value) in
                if let count = statistic.sumQuantity() {
                    // #6
                    val = Int(count.doubleValue(for: HKUnit.count()))
                }
            }
        }
        // #7
    }
    // #3
    healthStore.execute(query)
    // #4
    completion(val)
}

请注意,#4在#6之前执行。


解决方案是将completion移动到异步块内:

private func getSteps(completion: (Int) -> ()) {
    ...
    query.initialResultsHandler = { query,result,error in
        if let myresult = result {
            myresult.enumerateStatistics(from: startDate, to: Date()) { (statistic, value) in
                if let count = statistic.sumQuantity() {
                    val = Int(count.doubleValue(for: HKUnit.count()))
                }
            }
        }
        completion(val) // <- move here
    }
    healthStore.execute(query)
}