保存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
相关产品推荐
相关产品推荐

