ios - 从 Health App 实时获取新的心率数据?
问题描述
我正在尝试根据用户的实时心率数据构建 iPhone 应用程序。我能够从 Health App 获得最新的心率,但是一旦记录了新信息,该应用程序直到重新启动才会更新。
有没有办法实时获取心率数据?也许使用 HKObserverQuery?
到目前为止,这是我的代码:(谁设法拉动最后一次心跳)
import Foundation
import UIKit
import HealthKit
class HealthStore {
var healthStore: HKHealthStore?
init() {
if HKHealthStore.isHealthDataAvailable(){
healthStore = HKHealthStore()
}
}
func requestAuthorization(completion: @escaping (Bool) -> Void){
let heartBeat = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRate)!
guard let healthStore = self.healthStore else {return completion(false)}
healthStore.requestAuthorization(toShare: [], read: [heartBeat]) { (success, error) in completion(success)
}
}
func latestHarteRate(){
guard let sampleType = HKObjectType.quantityType(forIdentifier: .heartRate) else {
return
}
let startDate = Calendar.current.date(byAdding: .month, value: -1, to: Date())
let predicate = HKQuery.predicateForSamples(withStart: startDate, end: Date(), options: .strictEndDate)
let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: false)
let query = HKSampleQuery(sampleType: sampleType, predicate: predicate, limit: Int(HKObjectQueryNoLimit), sortDescriptors: [sortDescriptor]){(sample,result,error) in guard error == nil else{
return
}
let data = result![0] as! HKQuantitySample
let unit = HKUnit(from: "count/min")
let latestHr = data.quantity.doubleValue(for: unit)
print("Latest Hr\(latestHr) BPM")
healthStore?.execute(query)
}
解决方案
您可以使用 anHKAnchoredObjectQuery
创建一个查询,该查询返回一组初始数据,然后更新该数据集。
不幸的是,您无法为 提供排序描述符HKAnchoredObjectQuery
,因此如果您不想升序,则需要在收到数据后对数据进行排序。
这是我创建的模型对象,以便我可以在 SwiftUI 中进行测试。
它创建一个HKAnchoredQuery
并设置一个更新处理函数。更新处理程序将 HealthKit 结果转换为我的HeartRateEntry
结构(这样我就可以轻松地在 SwiftUI 列表中显示数据)。然后数组按日期降序排序。
更新功能存储newAnchor
接收到的内容,以便将来仅交付更改。
在测试时,我发现在手表上运行心率应用程序,将我的测试应用程序移到后台然后切换回它会比等待新数据传输更快地触发新的心率数据。
import Foundation
import HealthKit
struct HeartRateEntry: Hashable, Identifiable {
var heartRate: Double
var date: Date
var id = UUID()
}
class HeartHistoryModel: ObservableObject {
@Published var heartData: [HeartRateEntry] = []
var healthStore: HKHealthStore
var queryAnchor: HKQueryAnchor?
var query: HKAnchoredObjectQuery?
init() {
if HKHealthStore.isHealthDataAvailable() {
healthStore = HKHealthStore()
} else {
fatalError("Health data not available")
}
self.requestAuthorization { authorised in
if authorised {
self.setupQuery()
}
}
}
func requestAuthorization(completion: @escaping (Bool) -> Void){
let heartBeat = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRate)!
self.healthStore.requestAuthorization(toShare: [], read: [heartBeat]) { (success, error) in completion(success)
}
}
func setupQuery() {
guard let sampleType = HKObjectType.quantityType(forIdentifier: .heartRate) else {
return
}
let startDate = Calendar.current.date(byAdding: .month, value: -1, to: Date())
let predicate = HKQuery.predicateForSamples(withStart: startDate, end: .distantFuture, options: .strictEndDate)
self.query = HKAnchoredObjectQuery(type: sampleType, predicate: predicate, anchor: queryAnchor, limit: HKObjectQueryNoLimit, resultsHandler: self.updateHandler)
self.query!.updateHandler = self.updateHandler
healthStore.execute(self.query!)
}
func updateHandler(query: HKAnchoredObjectQuery, newSamples: [HKSample]?, deleteSamples: [HKDeletedObject]?, newAnchor: HKQueryAnchor?, error: Error?) {
if let error = error {
print("Health query error \(error)")
} else {
let unit = HKUnit(from: "count/min")
if let newSamples = newSamples as? [HKQuantitySample], !newSamples.isEmpty {
print("Received \(newSamples.count) new samples")
DispatchQueue.main.async {
var currentData = self.heartData
currentData.append(contentsOf: newSamples.map { HeartRateEntry(heartRate: $0.quantity.doubleValue(for: unit), date: $0.startDate)
})
self.heartData = currentData.sorted(by: { $0.date > $1.date })
}
}
self.queryAnchor = newAnchor
}
}
}
推荐阅读
- javascript - jQuery - 5秒后重定向网页
- java - 用于生成有效 SOAP 标头的 OpenSAML 实现
- android - 我无法使用 Android Studio 预览某些布局
- sql - 如何通过将持续时间添加到开始日期 SQL 来更新结束日期
- mosquitto - 有多少用户可以接受 mosquitto 用户列表?
- robotframework - Robot Framework 中的无头测试
- python-3.x - 将 python 2 转换为 python 3('PROCESS_ALL_ACCESS' 未定义)
- hibernate - 如何在 SELECT 查询中制作休眠前缀 N?
- asp.net-mvc - 用控件填写表单(根据服务返回的数据)
- excel - 创建具有多个工作条件的 IF 语句