如何在 iOS 9.3 中加速 HKStatisticsCollectionQuery?

How to speed up HKStatisticsCollectionQuery in iOS 9.3?

HKStatisticsCollectionQuery 在 iOS 9.3 中似乎非常慢。对于一年的活动卡路里,可能需要超过 40 秒才能完成 return 小时统计,而以前需要 1 或更少。

let predicate = HKQuery.predicateForSamplesWithStartDate(anchorDate, endDate: endDate, options: [])
    let query = HKStatisticsCollectionQuery(quantityType: quantityType,
        quantitySamplePredicate: predicate,
        options: statisticOptions,
        anchorDate: anchorDate,
        intervalComponents: interval)

经过数小时的反复试验,我发现 HKStatisticsCollectionQuery 不是线程友好的。为了解决这个问题,我使用了这个异步 NSOperation: https://gist.github.com/calebd/93fa347397cec5f88233

当然还有 NSOperationQueue,以强制同步执行 HKStatisticsCollectionQuerys。一旦我这样做了,每个查询花费的时间不到半秒。

如果有人对长时间的 HKStatisticsCollectionQuery 请求执行(几十秒或几分钟)有困难,请考虑您已经为谓词和锚点设置了正确的日期。问题是HealthKit要计算的数据很多。

例如,您的目标是收集今天的数据:

let predicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate)
    let query = HKStatisticsCollectionQuery(quantityType: quantityType,
                                            quantitySamplePredicate: predicate,
                                            options: .cumulativeSum,
                                            anchorDate: anchorDate,
                                            intervalComponents: interval)

这里startDate是今天的开始,endDate是明天的开始,anchorDate是一些一天的开始 - 在我的例子中它等于结束日期。

重要提示:如果你传递 nil 而不是 predicate,HealthKit 会从一开始就收集所有数据,结果会浪费你的时间。 为什么明天的开始必须作为结束日期?原因是statisticsUpdateHandler。由于您决定在 HealthKit 中监听数据更新,谓词的结束日期应该是未来的日期,而不是 Date()。如果您不想使用 statisticsUpdateHandler,您可以将结束日期设置为现在。