You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从Health Store获取最高采样率的历史心率数据?

解决Health Store心率数据细粒度读取与高频数据获取问题

1. 读取Quantity Series中的单个心率数据点

你提到的Quantity Series确实是存储连续心率数据的容器,普通的HKSampleQuery只能返回样本的元数据(比如起止时间、单位),无法直接读取其中的单个数据点。要获取系列内的每个BPM数据,需要使用HKQuantitySeriesQuery。

具体实现步骤:

  • 先通过HKSampleQuery获取HKQuantitySeriesSample实例(需做类型转换)
  • 针对每个系列样本,创建HKQuantitySeriesQuery读取内部所有数据点

修改后的代码示例:

public func fetchHeartRateSeriesData(completion: @escaping ([(date: Date, bpm: Double)]?) -> Void) {
    guard let heartRateType = HKObjectType.quantityType(forIdentifier: .heartRate) else {
        completion(nil)
        return
    }

    let predicate = HKQuery.predicateForSamples(withStart: Date.distantPast, end: Date(), options: .strictEndDate)
    let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: false)

    // 先查询所有心率系列样本
    let sampleQuery = HKSampleQuery(sampleType: heartRateType,
                                    predicate: predicate,
                                    limit: Int(HKObjectQueryNoLimit),
                                    sortDescriptors: [sortDescriptor]) { _, results, error in
        guard let samples = results as? [HKQuantitySample], error == nil else {
            completion(nil)
            return
        }

        var allHeartRateData: [(date: Date, bpm: Double)] = []
        let group = DispatchGroup()

        // 遍历每个系列样本,读取内部数据点
        for sample in samples {
            guard let seriesSample = sample as? HKQuantitySeriesSample else {
                continue
            }

            group.enter()
            let seriesQuery = HKQuantitySeriesQuery(quantitySeries: seriesSample) { _, timeInterval, quantity, done, error in
                guard let quantity = quantity, error == nil else {
                    group.leave()
                    return
                }

                // 转换单位:counts per second → beats per minute
                let bpm = quantity.doubleValue(for: HKUnit.count().unitDivided(by: HKUnit.second())) * 60
                let dataPointDate = seriesSample.startDate.addingTimeInterval(timeInterval)
                allHeartRateData.append((date: dataPointDate, bpm: bpm))

                if done {
                    group.leave()
                }
            }

            self.healthStore.execute(seriesQuery)
        }

        group.notify(queue: .main) {
            // 按时间排序(可选,根据需求调整)
            let sortedData = allHeartRateData.sorted { $0.date < $1.date }
            completion(sortedData)
        }
    }

    healthStore.execute(sampleQuery)
}

关键说明:

  • HKQuantitySeriesQuery的回调会逐次返回系列内的每个数据点,timeInterval是数据点相对于样本起始时间的偏移量
  • 心率数据默认存储单位为counts per second,需乘以60转换为常用的BPM单位
  • 使用DispatchGroup处理多个异步查询的结果汇总,确保所有数据读取完成后再返回

2. 高频心率数据的获取条件

要拿到5-10秒间隔的心率数据,必须满足以下条件:

  • 用户佩戴的Apple Watch已开启连续心率监测(在iPhone的Watch应用「心率」设置中开启)
  • 用户处于活动状态(如运动),此时Watch会自动提高心率采样频率;静态状态下采样间隔会变长(可能1分钟甚至更久)
  • 设备处于正常佩戴状态,心率传感器能正常采集数据

3. Apple是否默认存储高频心率数据?

不会默认存储所有高频数据:

  • 只有当设备满足上述监测条件(佩戴、开启连续监测、活动状态)时,Watch才会记录高频心率数据并同步到Health Store
  • 如果用户未开启连续心率监测,或设备未佩戴,Health Store中只会有低频率的心率数据(比如每几分钟一次)
  • 你无法获取Health Store中不存在的数据,必须依赖设备实际记录并同步的数据

内容的提问来源于stack exchange,提问作者CofeeBean42

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 11:49:54