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

如何用SwiftUI原生Charts库实现单月多数据柱状图

解决方案

1. 修复Identifiable协议错误

报错[OrdersHistory] must conform to Identifiable是因为SwiftUI原生Chart组件需要数据源中的元素能被唯一标识,最简单的解决方式是让OrdersHistory结构体遵循Identifiable协议,添加自动生成的唯一ID:

import Foundation

struct OrdersHistory: Identifiable {
    // 自动生成唯一ID,满足Identifiable协议要求
    let id = UUID()
    let date: Date
    let completed: Int
    let cancelled: Int
    let pending: Int
}

如果不想修改结构体,也可以在初始化Chart时显式指定标识字段(比如用date作为唯一标识):

Chart(ordersData, id: \.date) { /* ... */ }

2. 实现单月三组数据的柱状图

将原UIKit的ViewController逻辑迁移为SwiftUI视图,使用原生Chart组件创建分组柱状图(每个日期对应3组数据的柱子):

SwiftUI图表视图代码

import SwiftUI
import Charts

struct OrdersChartView: View {
    let ordersData: [OrdersHistory]
    
    // 格式化日期为当月的日(如1-31)
    private func formatDay(_ date: Date) -> String {
        let formatter = DateFormatter()
        formatter.dateFormat = "d"
        return formatter.string(from: date)
    }
    
    var body: some View {
        Chart(ordersData) { order in
            // 已完成订单柱状条
            BarMark(
                x: .value("日期", formatDay(order.date)),
                y: .value("已完成", order.completed)
            )
            .foregroundStyle(.green)
            
            // 已取消订单柱状条
            BarMark(
                x: .value("日期", formatDay(order.date)),
                y: .value("已取消", order.cancelled)
            )
            .foregroundStyle(.red)
            
            // 待处理订单柱状条
            BarMark(
                x: .value("日期", formatDay(order.date)),
                y: .value("待处理", order.pending)
            )
            .foregroundStyle(.orange)
        }
        .chartXAxisLabel("日期")
        .chartYAxisLabel("订单数量")
        .chartLegend(position: .bottom) // 图例放在底部
        .padding()
    }
}

在UIKit中嵌入SwiftUI图表

如果需要保留原ViewController(UIKit环境),可以通过UIHostingController嵌入SwiftUI视图:

import UIKit
import SwiftUI

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 生成测试数据(替换为你的真实数据)
        let sampleData: [OrdersHistory] = [
            OrdersHistory(date: Calendar.current.date(from: DateComponents(year: 2024, month: 5, day: 1))!, completed: 5, cancelled: 2, pending: 3),
            OrdersHistory(date: Calendar.current.date(from: DateComponents(year: 2024, month: 5, day: 2))!, completed: 7, cancelled: 1, pending: 2),
            OrdersHistory(date: Calendar.current.date(from: DateComponents(year: 2024, month: 5, day: 3))!, completed: 3, cancelled: 4, pending: 1),
            // 可继续添加当月其他日期的数据
        ]
        
        // 嵌入SwiftUI图表视图
        let chartView = OrdersChartView(ordersData: sampleData)
        let hostingController = UIHostingController(rootView: chartView)
        addChild(hostingController)
        hostingController.view.frame = view.bounds
        view.addSubview(hostingController.view)
        hostingController.didMove(toParent: self)
    }
}

3. 可选:堆叠柱状图

如果需要将三组数据堆叠显示(而非分组),只需给每个BarMark添加stacking(.value)修饰符:

BarMark(/* ... */)
.foregroundStyle(.green)
.stacking(.value)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 23:47:42