如何检测设备是否设置了 HealthKit 数据?

How to detect if HealthKit data is set from a device?

我正在尝试从 HealthKit 获取用户步骤并意识到用户可以手动添加我不想获取的步骤。 (例如,如果他们在一天内作弊并设置了 50k 步)。

所以我在考虑如何解决这个问题,并发现如果数据是由设备设置的,也许我可以过滤所有结果并获取数据。我的意思是它可以由 iPhone 设置,但也可以由 Apple Watch 设置。

以下是用户在“健康”应用中手动添加 his/hers 自己的步数时的样子:

这是设备添加步骤后的样子:

因此当数据由设备设置时,我们可以在 Health-app 中看到来自设备的更多信息,而不是用户手动设置数据。

问题是:如何查找结果中是否有设备?

我当前获取结果的代码:

func getSteps(completion: @escaping (Double, Error?) -> ()) {
    let stepsQuantityType = HKQuantityType.quantityType(forIdentifier: .stepCount)!
           
    let query = HKSampleQuery(sampleType: stepsQuantityType, predicate: nil, limit: 0, sortDescriptors: nil){ query, results, error in
        if let error = error {
            // Handle error
        } else if let results = results, !results.isEmpty {
            for result in results {
                // Detect and add result if result is from a device
            }
        }
    }

    HKHealthStore().execute(query)
}

我刚刚意识到我可以通过 result.device 检测设备是否存在,其中 device 是一个可选值。通过这样做,我可以检查该值是否为 nil

func getSteps(completion: @escaping (Double, Error?) -> ()) {
    let stepsQuantityType = HKQuantityType.quantityType(forIdentifier: .stepCount)!


    let query = HKSampleQuery(sampleType: stepsQuantityType, predicate: nil, limit: 0, sortDescriptors: nil){ query, results, error in
        if let error = error {
            // Handle error
        } else if let results = results, !results.isEmpty {
            for result in results {
                if result.device != nil {
                    // Result is from a device
                } else {
                    // Not a device
                }
            }
        }
    }

    HKHealthStore().execute(query)
}
let predicateAvoidManuallyLoggedData = HKQuery.predicateForObjects(withMetadataKey: HKMetadataKeyWasUserEntered, operatorType: .notEqualTo, value: true)

在 HKSample 或 Statistics 查询中使用上述谓词。

您也可以像这样组合谓词

  let predicate = NSCompoundPredicate(andPredicateWithSubpredicates: 
  [predicateSource, predicateTimePeriod, predicateAvoidManuallyLoggedData])