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

获取带电压数据的单条iOS ECG测量值致Flutter应用崩溃

解决Flutter iOS ECG电压数据获取崩溃问题

核心崩溃原因分析

EXC_BAD_ACCESS错误指向空指针访问,结合代码排查,问题根源在于:

  • HKElectrocardiogramQuery对象执行后被ARC自动释放,异步回调时访问已回收的内存
  • 多线程环境下对ecgs、measurments等变量的修改存在线程安全隐患
  • 批量查询时变量生命周期与异步回调不匹配,导致内存异常

具体解决方法

1. 强引用查询对象,避免提前释放

在循环创建voltageQuery后,将其存入一个闭包内的数组中,直到查询完成再移除,防止ARC提前回收对象。

2. 保证线程安全

使用串行队列或锁保护对ecgs和measurments的修改操作,避免多线程竞争引发的内存问题。

3. 优化内存与初始化逻辑

  • 若ECG样本数量较多,可分批发起查询,降低内存占用
  • 检查Electrocardiogram和VoltageMeasurement的初始化代码,避免强制解包空值

修改后的Swift代码示例

let query = HKSampleQuery(
    sampleType: type,
    predicate: predicate,
    limit: limit,
    sortDescriptors: sortDescriptors
) { (query, data, error) in
    guard
        error == nil,
        let results = data as? [HKElectrocardiogram]
    else {
        resultsHandler([], error)
        return
    }
    
    var ecgs: [Electrocardiogram] = []
    var ecgsError: Error?
    let group = DispatchGroup()
    let serialQueue = DispatchQueue(label: "com.ecg.query.queue")
    // 强引用查询对象,防止提前释放
    var activeQueries: [HKElectrocardiogramQuery] = []
    
    switch withVoltageMeasurements {
    case true:
        for ecgSample in results {
            group.enter()
            var measurements = [Electrocardiogram.VoltageMeasurement]()
            
            let voltageQuery = HKElectrocardiogramQuery(ecgSample) { (query, result) in
                serialQueue.async {
                    switch(result) {
                    case .measurement(let voltageMeasurement):
                        if let measurement = try? Electrocardiogram.VoltageMeasurement(voltageMeasurement: voltageMeasurement) {
                            measurements.append(measurement)
                        }
                    case .done:
                        if let ecg = try? Electrocardiogram(electrocardiogram: ecgSample, voltageMeasurements: measurements) {
                            ecgs.append(ecg)
                        }
                        // 移除已完成的查询
                        if let index = activeQueries.firstIndex(where: { $0 === query }) {
                            activeQueries.remove(at: index)
                        }
                        group.leave()
                    case .error(let error):
                        ecgsError = error
                        if let index = activeQueries.firstIndex(where: { $0 === query }) {
                            activeQueries.remove(at: index)
                        }
                        group.leave()
                    @unknown default:
                        ecgsError = HealthKitError.notAvailable("Unknown case of Electrocardiogram.VoltageMeasurement result")
                        if let index = activeQueries.firstIndex(where: { $0 === query }) {
                            activeQueries.remove(at: index)
                        }
                        group.leave()
                    }
                }
            }
            // 强引用查询对象
            activeQueries.append(voltageQuery)
            healthStore.execute(voltageQuery)
        }
        
        group.notify(queue: .global()) {
            resultsHandler(ecgs, ecgsError)
        }
    case false:
        ecgs = Electrocardiogram.collect(results: results)
        resultsHandler(ecgs, nil)
    }
}

额外建议

  • 优先测试单条ECG数据的获取,逐步验证稳定性后再批量查询
  • 确认HealthKit权限申请完整,包含ECG相关的读写权限
  • 排查Electrocardiogram.VoltageMeasurement初始化方法,确保所有可选值都做了安全处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 01:00:27