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

保存HKQuantitySample到HKHealthStore后,completion内sourceRevision未初始化

问题:HealthKit保存样本后sourceRevision未初始化的解决思路

我通过HKHealthStore.save(_:withCompletion:)方法将新建的HKQuantitySample保存到HealthKit后,在completion闭包中检查该样本的sourceRevision时,发现其处于<uninitialized>状态,无法调用dietaryWaterSample.sourceRevision.source.bundleIdentifier。相关代码如下:

let dietaryWaterQuantity = HKQuantity(unit: HKUnit.literUnit(with: .milli), doubleValue: 100)
let dietaryWaterSample = HKQuantitySample(type: HKSampleType.quantityType(forIdentifier: .dietaryWater)!,
                                          quantity: dietaryWaterQuantity,
                                          start: Date(),
                                          end: Date())

HKHealthStore().save(dietaryWaterSample) { success, error in
   /// dietaryWaterSample.sourceRevision is <uninitialized> so I cannot use dietaryWaterSample.sourceRevision.source.bundleIdentifier
}

解决思路

原因

你本地创建的HKQuantitySample对象在保存前,并没有被HealthKit填充完整的元数据(包括sourceRevision)。这部分信息是HealthKit在样本持久化后才会生成并赋值的,所以直接访问原对象的sourceRevision会处于未初始化状态。

方案1:保存成功后重新查询样本

利用样本的uuid作为唯一标识,在保存成功后向HealthKit发起查询,获取到的持久化样本会包含完整的sourceRevision信息:

let dietaryWaterQuantity = HKQuantity(unit: HKUnit.literUnit(with: .milli), doubleValue: 100)
let dietaryWaterSample = HKQuantitySample(type: HKSampleType.quantityType(forIdentifier: .dietaryWater)!,
                                          quantity: dietaryWaterQuantity,
                                          start: Date(),
                                          end: Date())
let healthStore = HKHealthStore()

healthStore.save(dietaryWaterSample) { success, error in
    guard success, error == nil else {
        // 处理保存失败逻辑
        return
    }

    // 通过UUID查询保存后的样本
    let predicate = HKQuery.predicateForObjects(withUUID: dietaryWaterSample.uuid)
    let query = HKSampleQuery(sampleType: dietaryWaterSample.sampleType, predicate: predicate, limit: 1, sortDescriptors: nil) { _, samples, error in
        guard let savedSample = samples?.first as? HKQuantitySample, error == nil else {
            // 处理查询失败逻辑
            return
        }
        // 此时可正常访问sourceRevision
        let bundleId = savedSample.sourceRevision.source.bundleIdentifier
        print(bundleId)
    }

    healthStore.execute(query)
}

方案2:使用iOS 13+新增的保存方法(更简洁)

iOS 13及以上版本中,HKHealthStore提供了save(_:to:withCompletion:)方法,其completion闭包会直接返回保存后的完整样本对象,无需额外查询:

let dietaryWaterQuantity = HKQuantity(unit: HKUnit.literUnit(with: .milli), doubleValue: 100)
let dietaryWaterSample = HKQuantitySample(type: HKSampleType.quantityType(forIdentifier: .dietaryWater)!,
                                          quantity: dietaryWaterQuantity,
                                          start: Date(),
                                          end: Date())
let healthStore = HKHealthStore()

// 传入nil使用默认容器
healthStore.save(dietaryWaterSample, to: nil) { savedSample, error in
    guard let savedSample = savedSample as? HKQuantitySample, error == nil else {
        // 处理失败逻辑
        return
    }
    // 直接使用返回的样本访问sourceRevision
    let bundleId = savedSample.sourceRevision.source.bundleIdentifier
    print(bundleId)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 05:53:12