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

FireStore数据填充Charts图表重叠及按时间排序需求

Swift Charts图表重叠+FireStore数据按时间排序填充问题

问题描述

我用Swift语言,借助Charts库绘制图表时,从FireStore读取数据填充出现图表重叠问题。同时希望能按时间顺序填充图表数据,当前FireStore数据结构如图(注:原提问提及有图但未提供)。作为新手寻求帮助,我的代码如下:

func LiveChart() {
        db.collection("Admin").document("AiSmartRobot").collection("AiDailyProfit").addSnapshotListener({ [self] (querySnapShot, error) in
            
            for document in querySnapShot!.documents{
                
                if let quantity = document.data()["quantity"] as? Double{
                    if let datetime = document.data()["date"] as? String{
                        
                        let barChartView = BarChartView(frame: live.bounds)
                        barChartView.delegate = self
                        barChartView.xAxis.labelPosition = .bottom
                        
                        let xValues = [datetime]
                        barChartView.xAxis.valueFormatter = IndexAxisValueFormatter(values: xValues)
                        self.live.addSubview(barChartView)
                        var values = [BarChartDataEntry]()
                        let numbers : [Double] = [quantity]
                        for i in 0..<numbers.count {
                            let value = BarChartDataEntry(x: Double(i), y: numbers[i])
                            values.append(value)
                        }
                        let ds = BarChartDataSet(values: values, label: "")
                        let data = BarChartData(dataSets: [ds])
                        ds.valueColors = [UIColor(red: 57.0/255.0, green: 176.0/255.0, blue: 158.0/255.0, alpha: 1)]
                        barChartView.data = data
                        barChartView.chartDescription?.text = ""
                        barChartView.animate(yAxisDuration: 2)
                        barChartView.notifyDataSetChanged()
                        
                    }
                    
                }
                
            }
        })
    }

解决方案

1. 解决图表重叠问题

你当前代码的核心问题是在每个FireStore文档的循环里都创建了新的BarChartView并添加到live容器中,导致每次数据更新都会叠加一个新图表,最终出现重叠。正确做法是提前创建一次图表视图,后续只更新数据。

2. 解决按时间顺序填充问题

FireStore查询默认不排序,需要给查询添加排序规则;同时要先收集所有有效数据,确保顺序正确后再转换为图表数据,避免逐个文档处理导致的顺序混乱。

修改后的完整代码示例

首先在视图控制器类中声明图表属性:

var barChartView: BarChartView!

然后在viewDidLoad中初始化图表视图并添加到容器:

override func viewDidLoad() {
    super.viewDidLoad()
    
    // 初始化图表视图,一次性创建
    barChartView = BarChartView(frame: live.bounds)
    barChartView.delegate = self
    barChartView.xAxis.labelPosition = .bottom
    barChartView.chartDescription?.text = ""
    live.addSubview(barChartView)
    
    // 启动数据监听
    LiveChart()
}

最后修改LiveChart函数:

func LiveChart() {
    db.collection("Admin").document("AiSmartRobot").collection("AiDailyProfit")
        .order(by: "date") // 关键:让FireStore按date字段排序返回数据
        .addSnapshotListener({ [self] (querySnapShot, error) in
            // 安全解包数据,处理错误
            guard let documents = querySnapShot?.documents else {
                print("获取数据失败: \(error?.localizedDescription ?? "未知错误")")
                return
            }
            
            // 收集所有有效数据
            var chartItems = [(date: String, quantity: Double)]()
            for document in documents {
                if let quantity = document.data()["quantity"] as? Double,
                   let dateStr = document.data()["date"] as? String {
                    chartItems.append((date: dateStr, quantity: quantity))
                }
            }
            
            // 如果FireStore的排序不满足需求(比如date是自定义格式),可以在客户端二次排序
            // chartItems.sort { $0.date < $1.date } // 根据实际日期格式调整排序逻辑
            
            // 转换为图表需要的Entry和X轴标签
            var chartEntries = [BarChartDataEntry]()
            var xLabels = [String]()
            for (index, item) in chartItems.enumerated() {
                chartEntries.append(BarChartDataEntry(x: Double(index), y: item.quantity))
                xLabels.append(item.date)
            }
            
            // 更新图表数据
            let dataSet = BarChartDataSet(values: chartEntries, label: "")
            dataSet.valueColors = [UIColor(red: 57.0/255.0, green: 176.0/255.0, blue: 158.0/255.0, alpha: 1)]
            let chartData = BarChartData(dataSets: [dataSet])
            
            barChartView.xAxis.valueFormatter = IndexAxisValueFormatter(values: xLabels)
            barChartView.data = chartData
            barChartView.animate(yAxisDuration: 2)
            barChartView.notifyDataSetChanged()
        })
}

关键修改说明

  • 移除循环内创建BarChartView的代码,改为在viewDidLoad中一次性创建,避免重复添加视图导致重叠
  • 添加order(by: "date")让FireStore直接返回排序后的数据,减少客户端处理压力
  • 先收集所有有效数据再统一处理,确保数据顺序正确后再更新图表
  • 安全解包数据,增加错误处理,避免强制解包querySnapShot导致崩溃

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 17:55:18