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

Swift 5搭配Charts 3.6.0绘制watchOS实时运动数据延迟问题求解

解决方案

核心优化逻辑

卡顿主要来源于三个问题:

  1. 使用DispatchQueue.main.sync阻塞了后台接收线程,导致大量更新任务堆叠在主队列等待执行
  2. 每次更新强制重索引所有条目的x值,加上全量刷新图表的操作额外增加了主线程开销
  3. 没有做更新限流,高采样率下大量重复更新任务抢占主线程资源

具体实现代码

第一步:新增更新锁属性

在ViewController类中新增全局标记,控制更新逻辑:

// 标记图表是否正在更新,更新期间新数据直接丢弃
private var isUpdatingChart = false

第二步:修改消息接收逻辑

收到数据时先判断更新状态,正在更新就直接丢弃:

func session(_ session: WCSession, didReceiveMessageData messageData: Data) {
    guard !isUpdatingChart else { return }
    isUpdatingChart = true
    let record : [Double] = try! NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSArray.self], from: messageData) as! [Double]
    laggyFunction(qaternions: [simd_quatd.init(ix: record[0], iy: record[1], iz: record[2], r: record[3])], quaternionTimes: [record[4]])
}

第三步:重构图表更新方法

替换同步调度为异步,删除不必要的x轴重索引逻辑,优化刷新方式:

private func laggyFunction(qaternions: [simd_quatd], quaternionTimes: [Double]) {
    DispatchQueue.main.async { [weak self] in
        guard let self = self, 
              let dataset = self.lineChartView.data?.getDataSetByIndex(0) else {
            self?.isUpdatingChart = false
            return
        }
        // 直接基于最后一条数据的x值新增,不需要重索引
        let currentMaxX = dataset.entryCount > 0 ? dataset.entryForIndex(dataset.entryCount - 1)!.x : 0
        var x = currentMaxX + 1
        for quaternion in qaternions {
            dataset.addEntry(ChartDataEntry(x: x, y: quaternion.vector.w))
            x += 1
        }
        // 保留最近5条数据
        while dataset.entryCount > 5 {
            dataset.removeFirst()
        }
        // 固定x轴范围,避免图表自动计算开销
        self.lineChartView.xAxis.axisMinimum = dataset.entryForIndex(0)!.x
        self.lineChartView.xAxis.axisMaximum = dataset.entryForIndex(dataset.entryCount - 1)!.x
        // 数据变更通知
        self.lineChartView.data?.notifyDataChanged()
        // 关闭所有动画,直接刷新
        self.lineChartView.animate(xAxisDuration: 0, yAxisDuration: 0)
        self.lineChartView.setNeedsDisplay()
        // 解锁允许下一次更新
        self.isUpdatingChart = false
    }
}

额外性能优化项

可以在viewDidLoad中提前关闭Charts不必要的渲染特性,进一步提升速度:

override func viewDidLoad() {
    super.viewDidLoad()
    self.lineChartView.leftAxis.axisMinimum = -1
    self.lineChartView.leftAxis.axisMaximum = 1
    
    // 关闭所有非必要特性
    lineChartView.highlightPerTapEnabled = false
    lineChartView.highlightPerDragEnabled = false
    lineChartView.legend.enabled = false
    lineChartView.xAxis.drawLabelsEnabled = false
    lineChartView.xAxis.drawGridLinesEnabled = false
    lineChartView.leftAxis.drawGridLinesEnabled = false
    lineChartView.rightAxis.enabled = false
    if let dataset = lineChartView.data?.getDataSetByIndex(0) as? LineChartDataSet {
        dataset.drawValuesEnabled = false
        // 如果不需要三次曲线可以改成.line,速度提升非常明显
        dataset.mode = .cubicBezier
        // 调低三次曲线平滑度换渲染速度
        dataset.cubicIntensity = 0.2
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 17:36:03