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

HealthKit如何查询同时获取HKQuantitySample和HKCumulativeQuantitySample心率样本

Apple Health心率查询兼容HKCumulativeQuantitySample类型调整方案

问题根源

你的原有代码仅支持捕获离散格式的HKQuantitySample心率样本,当有应用将心率以累积格式HKCumulativeQuantitySample存入健康库时,直接强转结果数组为[HKQuantitySample]的逻辑会直接丢弃所有累积类型的样本,导致数据缺失。

调整逻辑

  • 取消对查询结果整体的强转操作,逐一遍历返回的HKSample对象,分别匹配两种样本类型
  • 按需处理HKCumulativeQuantitySample的数值:可直接返回原始样本,也可将其转换为和HKQuantitySample格式统一的结构
  • 可根据业务需要选择返回原始多类型样本,或是统一转换为单一格式的样本集合

调整后代码

class func getHeartRateSamplesFrom(workout: HKWorkout, handler: @escaping ([HKQuantitySample]?, WorkoutManagerError?) -> Void) {
    guard let heartRateType: HKQuantityType = HKQuantityType.quantityType(forIdentifier: .heartRate) else {
        handler(nil, .init(errorDescription: "心率类型不可用"))
        return
    }

    let predicate = HKQuery.predicateForSamples(withStart: workout.startDate, end: workout.endDate, options: .strictStartDate)
    let sortDescriptors = [NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: false)]

    let heartRateQuery = HKSampleQuery(
        sampleType: heartRateType,
        predicate: predicate,
        limit: HKObjectQueryNoLimit,
        sortDescriptors: sortDescriptors
    ) { query, results, error in
        guard error == nil else {
            print("获取心率数据失败: \(error!.localizedDescription)")
            handler(nil, .init(errorDescription: "查询失败"))
            return
        }
        guard let unwrappedResults = results else {
            handler([], nil)
            return
        }
        
        var heartRateSamples = [HKQuantitySample]()
        for sample in unwrappedResults {
            // 匹配离散心率样本
            if let quantitySample = sample as? HKQuantitySample {
                heartRateSamples.append(quantitySample)
            }
            // 匹配累积心率样本,按需转换格式
            else if let cumulativeSample = sample as? HKCumulativeQuantitySample {
                // 此处示例直接提取累积总和生成等效HKQuantitySample
                // 若业务需要平均心率,可自行计算时间段长度后换算
                let convertedSample = HKQuantitySample(
                    type: heartRateType,
                    quantity: cumulativeSample.sumQuantity,
                    start: cumulativeSample.startDate,
                    end: cumulativeSample.endDate,
                    device: cumulativeSample.device,
                    metadata: cumulativeSample.metadata
                )
                heartRateSamples.append(convertedSample)
            }
        }
        handler(heartRateSamples, nil)
    }
    HealthStoreSingleton.sharedInstance.healthStore.execute(heartRateQuery)
}

注意事项

  • HKCumulativeQuantitySample存储的是某段时间内的心率总和,如果你的业务需要展示的是每个时间点的实时心率,可根据样本的时间跨度换算为平均心率后再生成新的样本。
  • 调用查询前请确保已经向用户申请了心率数据的读取权限,否则查询会返回空结果或权限错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 02:15:03