从 HKSampleQuery 获取最新的数据点

Get most recent data point from HKSampleQuery

我无法使用 HKSampleQuery 获取最新的体重数据点。我已正确设置应用程序权限,但 HKQuantityTypeIdentifier.bodyMass 未从健康应用程序返回最新的数据条目。

我应该如何使用 HKSampleQuery 获取最新的体重数据点?

我认为这是因为我为 Weight 设置的 0.0 是返回值,而我在 readWeight

上没有控制台输出

编辑 1

我的代码包括调试过程如下

public func readWeight(result: @escaping (Double) -> Void) {
    if (debug){print("Weight")}
    let quantityType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyMass)

    let weightQuery = HKSampleQuery(sampleType: quantityType!, predicate: nil, limit: 1, sortDescriptors: nil) {

        query, results, error in

        if (error != nil) {
            if (self.debug){print(error!)}
            result(166.2) //Set as average weight for American
            return
        }

        guard let results = results else {
            if (self.debug){print("No results of query")}
            result(166.2)
            return
        }

        if (results.count == 0) {
            if (self.debug){print("Zero samples")}
            result(166.2)
            return
        }

        guard let bodymass = results.first as? HKQuantitySample else {
            if (self.debug){print("Type problem with weight")}
            result(166.2)
            return
        }

        if (self.debug){print("Weight" + String(bodymass.quantity.doubleValue(for: HKUnit.pound())))}

        if (bodymass.quantity.doubleValue(for: HKUnit.pound()) != 0.0) {
            result(bodymass.quantity.doubleValue(for: HKUnit.pound()))
        } else {
            result(166.2)
        }
    }

    healthKitStore.execute(weightQuery)
}

函数是这样使用的:

var Weight = 0.0 //The probable reason that it returns 0.0
readWeight() { weight in
    Weight = weight
}

编辑 2

权限代码:

    let healthKitTypesToRead : Set<HKQuantityType> = [
        HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.dietaryWater)!,
        HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyMass)!,
        HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.appleExerciseTime)!
    ]

    let healthKitTypesToWrite: Set<HKQuantityType> = [
        HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.dietaryWater)!
    ]

    if (!HKHealthStore.isHealthDataAvailable()) {
        if (self.debug){print("Error: HealthKit is not available in this Device")}
        return
    }

    healthKitStore.requestAuthorization(toShare: healthKitTypesToWrite, read: healthKitTypesToRead) { (success, error) -> Void in
        if (success) {
            DispatchQueue.main.async() {
                self.pointView.text = String(self.currentPoints())
            }
        }

        if ((error) != nil) {
            if (self.debug){print(error!)}
            return
        }

HealthKit documentation 中所述(我强烈建议您完整阅读),HKSampleQuery 不保证其 return 中的样本或顺序它 return 是它们 除非 您指定样本应该如何 returned。

对于您的情况,return可以通过多种方式获取最新的数据点。看看HKSampleQuery和下面的方法:

init(sampleType:predicate:limit:sortDescriptors:resultsHandler:)

You can provide a sort order for the returned samples, or limit the number of samples returned.

-- HKSampleQuery Documentation

在您的代码中,您已适当限制查询,使其仅 return 一个样本。这是正确的,并且避免了您的用例中不必要的开销。但是,您的代码为 sortDescriptors 参数指定了 nil。这意味着查询可以 return 以任何它喜欢的顺序采样(因此,returned 给你的单个样本通常不是你要找的)。

An array of sort descriptors that specify the order of the results returned by this query. Pass nil if you don’t need the results in a specific order.

Note
HealthKit defines a number of sort identifiers (for example, HKSampleSortIdentifierStartDateand HKWorkoutSortIdentifierDuration). Use the sort descriptors you create with these identifiers only in queries. You cannot use them to perform an in-memory sort of an array of samples.

-- HKSampleQuery.init(...) Documentation

因此,解决方案是简单地提供一个排序描述符,要求 HKSampleQuery 按日期降序排列样本(这意味着最新的样本将在列表中排在第一位)。


我希望上面的答案比解决问题所需的简单 copy/paste 代码更有帮助。尽管如此,为 这个特定 用例提供正确样本的代码如下:

// Create an NSSortDescriptor
let sort = [
    // We want descending order to get the most recent date FIRST
     NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: false)
]

let weightQuery = HKSampleQuery(sampleType: quantityType!, predicate: nil, limit: 1, sortDescriptors: sort) {
    // Handle errors and returned samples...
}