HKLiveWorkoutDataSource如何为徒步等运动追踪Elevation升降海拔数据
解决HealthKit非滑雪类运动海拔升降统计的方案
核心说明
系统仅默认对单板滑雪、高山滑雪两类运动自动追踪上升/下降海拔数据,没有直接对应enableCollection的海拔采集接口,其他运动类型需要手动计算两项数值后写入Workout元数据。
实现步骤
- 方案1:实时计算(兼容全版本iOS)
- 用CoreMotion框架的CMAltimeter获取气压海拔变化,先校验设备支持:
import CoreMotion let altimeter = CMAltimeter() guard CMAltimeter.isRelativeAltitudeAvailable() else { // 设备不支持气压计,可降级使用GPS定位计算海拔差 return }- 开启海拔更新,累计升降数值:
var totalAscended: Double = 0 var totalDescended: Double = 0 var lastAltitude: Double? altimeter.startRelativeAltitudeUpdates(to: OperationQueue.main) { data, error in guard let data = data, error == nil else { return } let currentAlt = data.relativeAltitude.doubleValue if let last = lastAltitude { let diff = currentAlt - last if diff > 0 { totalAscended += diff } else if diff < 0 { totalDescended += abs(diff) } } lastAltitude = currentAlt }- 运动结束后将数值写入Workout元数据:
let workoutMetadata: [String: Any] = [ HKMetadataKeyElevationAscended: HKQuantity(unit: .meter(), doubleValue: totalAscended), HKMetadataKeyElevationDescended: HKQuantity(unit: .meter(), doubleValue: totalDescended) ] // 构造HKWorkout实例时传入metadata参数即可完成写入 - 方案2:iOS15+直接查询系统统计值
iOS15及以上系统新增了海拔升降的样本类型,运动结束后直接查询对应时间段的样本即可获取统计值,无需自行实时计算:// 查询上升海拔示例,下降海拔替换type为.elevationDescended即可 guard let ascType = HKQuantityType.quantityType(forIdentifier: .elevationAscended) else { return } let predicate = HKQuery.predicateForSamples(withStart: workoutStartTime, end: workoutEndTime, options: .strictStartDate) let query = HKStatisticsQuery(quantityType: ascType, quantitySamplePredicate: predicate, options: .cumulativeSum) { _, result, _ in guard let result = result, let sum = result.sumQuantity() else { return } let totalAsc = sum.doubleValue(for: .meter()) // 拿到数值后写入Workout元数据即可 } HKHealthStore().execute(query)
内容的提问来源于stack exchange,提问作者Roman Barzyczak
相关产品推荐
相关产品推荐

