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

如何从HealthKit训练样本元数据中读取HKMetadataKeyWeatherCondition?

解决HKWorkout无法获取HKMetadataKeyWeatherCondition的问题

核心原因与解决方向

Apple Fitness中显示的训练天气状况,通常并非直接存储在HKWorkout的metadata字典中,而是以独立的HKWeatherSample类型存在,需要单独查询并关联到对应的训练记录。以下是具体的解决步骤:


1. 单独查询HKWeatherSample样本

添加针对天气样本的查询逻辑,通过训练的时间范围匹配对应的天气数据:

func asyncWorkout() async throws {
    let workoutTypeValue: HKWorkoutActivityType = .running

    // 原有训练查询逻辑不变
    let predicate1 = HKQuery.predicateForSamples(withStart: Date().addingTimeInterval(-5*24*60*60), end: Date().addingTimeInterval(-3*24*60*60), options: .strictStartDate)
    let predicate2 = HKQuery.predicateForWorkouts(with: workoutTypeValue)
    let predicate = NSCompoundPredicate(type: .and, subpredicates: [predicate1, predicate2])

    var myAnchor: HKQueryAnchor?
    let anchorDescriptor = HKAnchoredObjectQueryDescriptor(
        predicates: [.workout(predicate)],
        anchor: myAnchor
    )

    let results = try await anchorDescriptor.result(for: healthStore)
    let addedSamples = results.addedSamples

    // 新增:查询天气样本
    guard let weatherType = HKObjectType.weatherSampleType() else {
        throw NSError(domain: "HealthKitError", code: -1, userInfo: [NSLocalizedDescriptionKey: "天气样本类型不可用"])
    }

    for workout in addedSamples {
        print("sample meta: \(String(describing: workout.metadata))")
        
        // 匹配训练时间范围的天气样本
        let weatherPredicate = HKQuery.predicateForSamples(withStart: workout.startDate, end: workout.endDate, options: .strictStartDate)
        let weatherDescriptor = HKSampleQueryDescriptor(
            predicate: weatherPredicate,
            sortDescriptors: [],
            limit: HKObjectQueryNoLimit,
            resultsType: weatherType
        )
        
        let weatherSamples = try await weatherDescriptor.result(for: healthStore)
        for weatherSample in weatherSamples {
            // 解析天气状况枚举
            if let conditionRawValue = weatherSample.metadata?[HKMetadataKeyWeatherCondition] as? Int,
               let condition = HKWeatherCondition(rawValue: conditionRawValue) {
                print("训练\(workout.uuid)对应的天气状况:\(condition.rawValue)")
            }
        }
    }

    myAnchor = results.newAnchor
}

2. 确认权限配置

  • 在Info.plist中添加HealthKit权限描述:
    • NSHealthShareUsageDescription:说明应用需要分享健康数据的原因
    • NSHealthUpdateUsageDescription:说明应用需要读取健康数据的原因
  • 请求天气样本的读取权限:
let typesToRead: Set<HKObjectType> = [
    HKObjectType.workoutType(),
    HKObjectType.weatherSampleType() // 必须添加这个权限
]
try await healthStore.requestAuthorization(toShare: nil, read: typesToRead)

3. 直接验证元数据键(备选方案)

如果怀疑枚举映射问题,可以直接用字符串键取值:

// 在遍历HKWorkout时尝试直接读取
if let conditionRawValue = workout.metadata?["HKWeatherCondition"] as? Int {
    let condition = HKWeatherCondition(rawValue: conditionRawValue) ?? .unknown
    print("天气状况:\(condition)")
}

4. 校验时间与时区匹配

检查Apple Fitness中显示的天气时间是否与训练的startDate/endDate完全匹配,避免时区差异导致查询范围遗漏数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 22:33:01