如何从具有 HKDevice 的 Health Kit 中查询样本

Posted

技术标签:

【中文标题】如何从具有 HKDevice 的 Health Kit 中查询样本【英文标题】:How to query for samples from health kit that have an HKDevice 【发布时间】:2018-06-21 19:27:10 【问题描述】:

我想从 HealthKit 查询样本,但为了防止数据不准确或被操纵,我不希望其他应用程序写入健康的样本。有谁知道我可以使用什么谓词来过滤掉所有应用程序中的数据或只允许来自设备的数据?提前致谢。

编辑:我意识到应用程序可以通过包含 HKDevice 将数据保存到健康。所以过滤掉没有设备的样本是行不通的。

【问题讨论】:

【参考方案1】:

如果您想要排除手动输入的数据,请参阅此答案:Ignore manual entries from Apple Health app as Data Source

用户通过 Health 添加到 HealthKit 的样本将具有 HKMetadataKeyWasUserEntered 键。

【讨论】:

我确实想排除手动数据,谢谢,但这篇文章更多的是关于从应用程序中排除数据。例如,我希望能够忽略模拟心率的应用中的样本。 您有模拟心率的应用的具体示例吗?除了手动输入之外,存储 HealthKit 中传感器未记录的数据的应用程序的目的是什么?如果您担心在某种竞争中作弊,没有什么可以阻止模拟数据的应用程序使用本地 HKDevice 获取数据。 不,我没有任何示例,但在我自己的应用程序中,我只需一个 Double 即可将心率样本直接存储到健康中。我没有过多考虑这样的应用程序可能具有什么合法目的,但我可以想象一个对调试目的有用的应用程序。其实我很担心作弊,你说得对,模拟数据可能有本地的HKDevice。正如您从我编辑的答案中看到的那样,尽管我添加了对“com.apple.health”捆绑标识符的检查。我假设应用程序无法模拟苹果捆绑 ID,但如果我错了,请纠正我。【参考方案2】:

我仍然愿意接受建议和替代解决方案,但这是我的解决方法,因为我无法弄清楚如何使用谓词来完成工作。

 let datePredicate = HKQuery.predicateForSamples(withStart:Date(), end: nil, options: [])

 let sampleQuery = HKAnchoredObjectQuery(type: sampleType,
                                               predicate: predicate,
                                               anchor: nil,
                                               limit: Int(HKObjectQueryNoLimit))  query,
                                                                                   samples,
                                                                                   deletedObjects,
                                                                                   anchor,
                                                                                   error in
        if let error = error 
            print("Error performing sample query: \(error.localizedDescription)")
            return
        

        guard let samples = samples as? [HKQuantitySample] else  return 

        // this line filters out all samples that do not have a device
        let samplesFromDevices = samples.filter  
            $0.device != nil && $0.sourceRevision.source.bundleIdentifier.hasPrefix("com.apple.health") 
        
        doStuffWithMySamples(samplesFromDevices)
    

如您所见,我只是在数据通过后对其进行过滤,而不是事先进行过滤。

编辑:似乎健康中列出的来源分为应用程序和实际设备。不是 100% 确定他们是如何做到这一点的,但似乎设备部分下的源都有一个以 com.apple.health 为前缀的包标识符。希望这行得通。

【讨论】:

【参考方案3】:

您可以在查询中过滤掉苹果未存储的结果,而不是迭代所有结果。

首先,您需要获取所需类型的所有来源。

let query = HKSourceQuery(sampleType: type,
                                  samplePredicate: predicate) 
                                    query, sources, error in
                                    
                                    // error handling ...
                                    
                                    // create a list of your desired sources
                                    let desiredSources = sources?.filter  
                                          !$0.bundleIdentifier.starts(with: "com.apple.health")
                                     
                                    
                                    // now use that list as a predicate for your query
                                    let sourcePredicate = HKQuery.predicateForObjects(from: desiredSources!)

                                    // use this predicate to query for data

        
        

您还可以使用NSCompoundPredicate 组合其他谓词

【讨论】:

以上是关于如何从具有 HKDevice 的 Health Kit 中查询样本的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Health Kit 断开 Health App 的源?

如何使用 Health Kit 断开 Health App 的源?

如何从 Swift 中的 Health Kit Sdk 中获取卡路里和心率?

从 Apple 的 Health 应用程序访问数据步数

如何在 iOS 应用程序中从 Health 应用程序获取活动的唯一标识符?

如何配置 Health Check?- 每天5分钟玩转 Docker 容器技术(107)