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

使用HKSourceQuery搭配predicateForWorkouts查询骑行训练源无返回值如何解决

HealthKit 骑行训练数据源查询问题解决方案

问题根因

返回的error和samples均为nil的问题,通常由以下几个原因导致:

  • 未主动向用户申请骑行训练数据的读取权限,HealthKit 对无权限的查询默认返回空结果,不会抛出错误
  • 代码实现遗漏了将构造好的查询实例加入健康存储执行的步骤
  • 测试环境使用模拟器,模拟器的健康数据同步机制存在缺陷,可能出现实体数据存在但查询不到的情况
  • 部分iOS 15早期版本存在HKSourceQuery的谓词匹配bug,会导致运动类型的过滤条件失效

解决步骤

1. 先申请健康数据读取权限

在发起查询前,必须先请求workout类型的读取权限,示例代码:

let healthStore = HKHealthStore()
let workoutType = HKObjectType.workoutType()

// 申请读取权限
healthStore.requestAuthorization(toShare: nil, read: [workoutType]) { success, error in
    guard success, error == nil else {
        print("权限申请失败", error!)
        return
    }
    // 权限申请通过后再发起查询
    queryCyclingSources()
}

2. 正确构造并执行HKSourceQuery

注意HKSourceQuery的回调第二个参数是数据源集合(Set<HKSource>),不是训练样本集合,你之前的参数名存在误解:

func queryCyclingSources() {
    let workoutPredicate = HKQuery.predicateForWorkouts(with: .cycling)
    let query = HKSourceQuery(
        sampleType: .workoutType(),
        samplePredicate: workoutPredicate
    ) { query, sources, error in
        // 此时sources就是所有产生过骑行训练的数据源集合
        print("数据源:\(sources ?? []),错误:\(error ?? "无错误")")
    }
    // 必须调用execute方法执行查询,否则回调不会触发
    healthStore.execute(query)
}

3. 异常兼容方案

如果你使用的系统版本存在谓词匹配bug,可以先全量查询所有运动数据源,再过滤出存在骑行训练的数据源:

func queryCyclingSourcesCompatibility() {
    // 先查询所有运动的数据源
    let query = HKSourceQuery(
        sampleType: .workoutType(),
        samplePredicate: nil
    ) { [weak self] query, allSources, error in
        guard let allSources = allSources else { return }
        // 遍历每个源,查询是否存在该源产生的骑行训练
        let group = DispatchGroup()
        var cyclingSources = Set<HKSource>()
        allSources.forEach { source in
            group.enter()
            let predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [
                HKQuery.predicateForWorkouts(with: .cycling),
                HKQuery.predicateForObjects(from: source)
            ])
            let countQuery = HKStatisticsQuery(
                quantityType: HKObjectType.quantityType(forIdentifier: .distanceCycling)!,
                quantitySamplePredicate: predicate,
                options: .cumulativeSum
            ) { _, result, _ in
                if result != nil {
                    cyclingSources.insert(source)
                }
                group.leave()
            }
            self?.healthStore.execute(countQuery)
        }
        group.notify(queue: .main) {
            print("所有骑行训练的数据源:\(cyclingSources)")
        }
    }
    healthStore.execute(query)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 19:48:02