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

明明存在数据,HKSampleQuery却返回无结果?附月心率获取代码

解决HKSampleQuery返回无结果的问题

看起来你遇到的问题主要出在日期范围的顺序和一些语法细节上,我帮你一步步排查和修正:

1. 核心问题:日期范围搞反了

HKQuery.predicateForSamples(withStart:end:options:) 要求 startDate 是时间范围的更早起始点,endDate 是更近的结束点。你现在的代码里:

let startDate = Date()
let endDate = Date() - 1.month

相当于查询「从现在到一个月前」的样本——这个时间逻辑是颠倒的,自然不会返回任何结果。

2. 修正日期范围

把日期顺序反过来,同时用系统Calendar来计算日期更可靠(避免自定义扩展可能带来的错误):

// 结束日期是当前时间
let endDate = Date()
// 推算一个月前的起始日期
guard let startDate = Calendar.current.date(byAdding: .month, value: -1, to: endDate) else {
    print("无法计算一个月前的日期")
    return
}

3. 修复Predicate的语法错误

你代码里的options: []...是语法错误,直接写options: []即可(如果不需要额外查询选项的话)。

完整修正后的代码示例

func getThisMonthsHeartRates() {
    print("func called")
    // 更规范的心率单位写法
    let heartRateUnit = HKUnit.count().unitDivided(by: HKUnit.minute())
    guard let heartRateType = HKQuantityType.quantityType(forIdentifier: .heartRate) else {
        print("无法获取心率数据类型")
        return
    }
    
    // 正确的时间范围:一个月前 → 现在
    let endDate = Date()
    guard let startDate = Calendar.current.date(byAdding: .month, value: -1, to: endDate) else {
        print("日期计算失败")
        return
    }
    
    let predicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate, options: [])
    
    // 构建并执行查询
    let query = HKSampleQuery(sampleType: heartRateType, predicate: predicate, limit: HKObjectQueryNoLimit, sortDescriptors: nil) { (query, samples, error) in
        DispatchQueue.main.async {
            if let error = error {
                print("查询出错:\(error.localizedDescription)")
                return
            }
            
            guard let heartRateSamples = samples as? [HKQuantitySample] else {
                print("未找到心率样本")
                return
            }
            
            // 提取时间与心率数值
            for sample in heartRateSamples {
                let heartRateValue = sample.quantity.doubleValue(for: heartRateUnit)
                let sampleTime = sample.startDate
                print("心率:\(heartRateValue) count/min,时间:\(sampleTime)")
            }
        }
    }
    
    // 别忘了初始化HealthStore并执行查询
    guard let healthStore = HKHealthStore() else {
        print("HealthStore初始化失败")
        return
    }
    healthStore.execute(query)
}

额外注意事项

  • 确保已经在Info.plist中添加了NSHealthShareUsageDescription和NSHealthUpdateUsageDescription权限描述,并且在代码中请求了心率数据的读取权限。
  • 如果你的1.month是自定义的Date扩展,检查它的实现是否正确(比如是否处理了不同月份的天数差异,比如3月31日往前推一个月应该是2月28/29日)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:12:07