来自 HealthKit 的数据最初丢失,然后在我再次尝试时出现 - 如何修复?

Data from HealthKit is initially missing, then comes in when I try again - how to fix?

我有一个正在 Swift 开发的 iOS 应用程序,作为该应用程序的一部分,它会收集当天的步数。

我第一次运行这个应用程序,计数是“0”,但是如果我点击界面中的一个按钮重新运行这个查询HK的功能,那么正确数字出现。

我猜这是因为 HK 需要一些时间来收集数据之类的,但我不确定如何修复它。也许 HK 可以在数据准备好后触发一个事件,然后我可以更新 UI?

这是从 HK 收集数据的例程。这个函数在应用程序启动时立即执行(它显示“今天0步”),然后如上所述,我可以点击一个按钮再次执行该函数(然后我得到正确的数字)。

    func queryStepsSum() {
        // prepare HK for the data
        let endDate = NSDate()          // right now
        let startDate = NSCalendar.currentCalendar().dateBySettingHour(0, minute: 0, second: 0, ofDate: endDate, options: NSCalendarOptions())
        let predicate = HKQuery.predicateForSamplesWithStartDate(startDate, endDate: endDate, options: .None)
        let sumOption = HKStatisticsOptions.CumulativeSum
        let statisticsSumQuery = HKStatisticsQuery( quantityType: self.stepsCount!, quantitySamplePredicate: predicate,
                                                    options: sumOption)
        { [unowned self] (query, result, error) in
            if let sumQuantity = result?.sumQuantity() {
                self.numberOfSteps = Int(sumQuantity.doubleValueForUnit(HKUnit.countUnit()))
            }
        }

        // run the HK query
        self.healthStore?.executeQuery(statisticsSumQuery)

        // update the UI with the result
        dispatch_async(dispatch_get_main_queue(), { () -> Void in
            self.stepsLabel.text = "\(self.numberOfSteps) steps today";
        });
    }

您是在 viewDidLoad 中调用您的函数吗?您可以尝试在 viewDidAppear 中调用它。 如果这不起作用,也许有某种委托方法可以像您说的那样在数据准备就绪时更新您。我从未使用过 HealthKit,但我会检查一下是否能找到任何东西。

编辑: 这可能会使 UI 组件脱离后台线程。 尝试:

var numberOfSteps: Int! {
    didSet {
        self.stepsLabel.text = "\(self.numberOfSteps) steps today"
    }
}

这应该可以消除您在后台线程上更新 UI 的错误。还要确保在我告诉你放置的闭包中删除你的调用。

您的代码在显示结果之前不会等待查询完成(查询是异步发生的)。您应该从查询的结果处理程序更新 UI,如下所示:

    let statisticsSumQuery = HKStatisticsQuery( quantityType: self.stepsCount!, quantitySamplePredicate: predicate,
                                                options: sumOption)
    { [unowned self] (query, result, error) in
        dispatch_async(dispatch_get_main_queue()) {
            if let sumQuantity = result?.sumQuantity() {
                self.numberOfSteps = Int(sumQuantity.doubleValueForUnit(HKUnit.countUnit()))
                self.stepsLabel.text = "\(self.numberOfSteps) steps today";
            }
        }
    }

另请注意,由于查询结果处理程序在后台线程上运行,并且在该上下文中操作 UI 不安全,因此我已经将调度返回到主线程。