You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

iOS:基于HealthKit框架实时获取血氧饱和度技术问询

实时获取Apple Watch血氧饱和度的HealthKit实现指南

嘿,作为HealthKit新手想做实时血氧监测,这个方向完全没问题!我来帮你完善你写的查询函数,再给你一些关键的注意事项,避免踩坑~

首先,咱们先把你没写完的createOxygenSaturationStreamingQuery函数补全,这里用HealthKit里适合实时监听数据的HKAnchoredObjectQuery(和你参考的心率仓库逻辑一致,适配性更好):

func createOxygenSaturationStreamingQuery(_ workoutStartDate: Date) -> HKAnchoredObjectQuery? {
    // 先确认血氧饱和度类型是否可用(部分旧设备不支持)
    guard let quantityType = HKObjectType.quantityType(forIdentifier: .oxygenSaturation) else {
        print("当前设备不支持血氧饱和度监测")
        return nil
    }
    
    // 设置查询范围:从指定开始时间到当前的所有血氧样本
    let datePredicate = HKQuery.predicateForSamples(withStart: workoutStartDate, end: nil, options: .strictStartDate)
    
    // 初始化锚点查询:初始锚点为nil会先返回所有历史数据,之后监听新数据
    let query = HKAnchoredObjectQuery(
        type: quantityType,
        predicate: datePredicate,
        anchor: nil,
        limit: HKObjectQueryNoLimit
    ) { [weak self] query, samples, deletedObjects, anchor, error in
        // 处理首次查询返回的历史数据
        if let error = error {
            print("初始血氧查询出错:\(error.localizedDescription)")
            return
        }
        self?.processOxygenSaturationSamples(samples)
    }
    
    // 设置更新回调:实时监听新产生的血氧样本
    query.updateHandler = { [weak self] query, samples, deletedObjects, anchor, error in
        if let error = error {
            print("血氧数据更新出错:\(error.localizedDescription)")
            return
        }
        self?.processOxygenSaturationSamples(samples)
    }
    
    return query
}

// 辅助函数:解析并处理血氧样本数据
private func processOxygenSaturationSamples(_ samples: [HKSample]?) {
    guard let quantitySamples = samples as? [HKQuantitySample] else { return }
    
    for sample in quantitySamples {
        // 血氧饱和度的单位是百分比(%),转换为可读的数值
        let saturationValue = sample.quantity.doubleValue(for: HKUnit.percent())
        let sampleDate = sample.startDate
        
        // 这里可以把数据更新到UI、存储或者做其他业务处理
        print("实时血氧饱和度:\(String(format: "%.1f%%", saturationValue)) | 采集时间:\(sampleDate)")
    }
}

接下来,还有几个必须注意的关键点,不然你的代码可能跑不起来:

1. 必须先申请健康数据权限

在使用任何HealthKit查询前,一定要先向用户申请血氧饱和度的读取权限:

let healthStore = HKHealthStore()

func requestOxygenSaturationPermissions() {
    guard let oxygenType = HKObjectType.quantityType(forIdentifier: .oxygenSaturation) else { return }
    
    let typesToRead: Set<HKObjectType> = [oxygenType]
    
    healthStore.requestAuthorization(toShare: nil, read: typesToRead) { success, error in
        DispatchQueue.main.async {
            if let error = error {
                print("权限申请失败:\(error.localizedDescription)")
            } else if success {
                print("血氧权限申请成功!可以开始查询数据了")
                // 权限通过后,启动实时查询
                let query = self.createOxygenSaturationStreamingQuery(Date())
                if let validQuery = query {
                    self.healthStore.execute(validQuery)
                }
            }
        }
    }
}

2. 设备兼容性检查

血氧监测只有Apple Watch Series 6及以上型号支持,而且用户需要在Watch的「健康」APP里开启血氧功能。你可以在代码里提前做兼容性判断:

func canMonitorOxygenSaturation() -> Bool {
    guard let oxygenType = HKObjectType.quantityType(forIdentifier: .oxygenSaturation) else { return false }
    return HKHealthStore.isHealthDataAvailable() 
        && healthStore.authorizationStatus(for: oxygenType) == .sharingAuthorized
        && HKHealthStore.supports(oxygenType)
}

3. 关于实时数据的小提醒

和心率不同,Apple Watch的血氧采样不是连续实时的——它主要在用户静止、睡眠时自动测量,或者用户手动在Watch上触发测量。如果你需要更主动的测量,可以引导用户手动启动,或者结合Workout模式(部分场景下会更频繁采样)。

4. 适配你参考的心率仓库

你参考的心率代码用的是HKAnchoredObjectQuery,血氧的逻辑完全可以复用这个模式,只需要把数据类型从心率换成血氧,处理样本时注意单位是HKUnit.percent()就好啦~

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

火山引擎 最新活动