图表lib滞后于滚动

Rec*_*iwe 7 charts uitableview ios swift

我刚刚在tableview中实现了库图表(https://github.com/danielgindi/Charts),但是当我的图表包含大量数据时,我在滚动期间遇到了相当大的延迟.

我在ChartTableViewCell中有一个方法,我根据传递的数据绘制图表,并从我的viewcontroller调用.

func updateCell(chartData: ChartData) {

    DispatchQueue.global(qos: .background).async {
        print("This is run on the background queue")
    self.readings = (readings != nil) ? readings!.readings : []
        self.period = period

        if (chartData.isKind(of: LineChartData.self)) {
            data.lineData = chartData as! LineChartData
        }
        else if (chartData.isKind(of: BarChartData.self)) {
            data.barData = chartData as! BarChartData
        }
    }

    DispatchQueue.main.async {
    self.chartView.data = data
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的tableViewController中,我在解析数据后调用该函数:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let meta = chartMetas[indexPath.row]
        let cell = tableView.dequeueReusableCell(withIdentifier: "chartCell", for: indexPath) as! ChartTableViewCell
        cell.readings = currentReadings
        cell.updateCell()

        return cell
    }
Run Code Online (Sandbox Code Playgroud)

我错过了什么?由于视图在滚动时非常困难.

更新:

我按照建议尝试在viewcontroller中准备图表数据并将其传递给单元格.然而,似乎是可重复使用的单元格中的问题,当我滚动并且新单元格进入屏幕时出现滞后.我怎样才能解决这个问题?这很烦人.

更新2:看起来图表不应该在tableview中使用... https://github.com/danielgindi/Charts/issues/3395

wot*_*tle 0

当存在大型数据集时,您的图表库可能会进行一些相当繁重的处理。如果这个库的作者没有考虑到这一点,那么每次滚动并且屏幕上出现一个新单元格时,您都会在主线程上执行这个繁重的处理。这肯定会导致口吃。

我希望更改单元格设置方法以简单地显示旋转器或占位符表,然后在后台线程上启动数据加载和图表构建。这应该会导致UITableView滚动平滑,但当您滚动表格时,您将看到带有占位符的单元格,其中图表在后台线程处理完成后填充。

在 Swift 中在后台线程上运行非常简单

只需确保当您准备好用图表更新 UI 时,您在主线程上执行此操作(所有 UI 更新应在主线程上执行,否则您会看到奇怪的视觉异常或更新 UI 的延迟)。因此,在后台线程上完成繁重的处理后,可能会隐藏占位符图像并在主线程上使用动画显示图表。

如果你做了这样的事怎么办?

func updateCell(chartData: ChartData) {

    DispatchQueue.global(qos: .background).async {
        print("This is run on the background queue")
    self.readings = (readings != nil) ? readings!.readings : []
        self.period = period

        if (chartData.isKind(of: LineChartData.self)) {
            data.lineData = chartData as! LineChartData
        }
        else if (chartData.isKind(of: BarChartData.self)) {
            data.barData = chartData as! BarChartData
        }     

        self.chartView.data = data

        DispatchQueue.main.async {
            // something that triggers redrawing of the chartView.
           chartView.fitScreen()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,主线程调用位于后台线程执行块内。这意味着所有内容都将在后台线程上运行,当后台线程内容完成时,它将调用图表库中的某些内容来刷新 UI。同样,如果您的图表库是为了强制在主线程上发生长时间运行的操作而编写的,那么这将无济于事。