【问题标题】:Completion handler returning before task finishes在任务完成之前返回的完成处理程序
【发布时间】:2020-08-04 23:12:05
【问题描述】:

我有这个函数,它有一个完成处理程序,任务完成后要返回,但从我得到的输出中,它表明完成处理程序被认为已完成并在任务完成之前返回。

被调用的函数:

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 而不是在函数内部设置 val 的 Int(count.doubleValue(for: HKUnit.count()))。任何关于为什么我得到 0 而不是 set val 的输入将不胜感激!

【问题讨论】:

    标签: swift healthkit completionhandler


    【解决方案1】:

    请注意,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)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-16
      • 1970-01-01
      • 1970-01-01
      • 2015-09-21
      相关资源
      最近更新 更多