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

Swift Charts:使Int枚举遵循Plottable协议以显示图例却无法正常显示的问题

解决Swift Charts中自定义Int枚举作为Plottable时图例不显示的问题

你的枚举实现Plottable的思路是对的,但图例不显示的核心原因是当前图表只渲染了Type.first的数据,Swift Charts无法识别到还有Type.second这个类别存在,即使你在chartForegroundStyleScale中定义了它。另外,我们可以简化Plottable的实现,因为Swift Charts已经为RawRepresentable类型提供了默认支持。

步骤1:简化枚举的Plottable实现

对于遵循RawRepresentable且原始类型是Plottable(比如Int)的枚举,你不需要手动实现Plottable的两个方法,Swift Charts会自动提供默认实现。修改后的枚举代码如下:

enum Type: Int, CaseIterable, Identifiable, Plottable {
    var id: Int { rawValue }
    case first = 32
    case second = 434
}

步骤2:让图表识别所有枚举类别

要让图例显示所有定义的样式,需要确保图表知道所有可能的枚举case,即使某个case没有对应的数据。你可以通过两种方式实现:

方式一:显式处理所有枚举case的数据

在图表中分别处理每个枚举case的数据,即使数据为空也保留结构,这样图表会识别到所有类别:

Chart {
    // 处理Type.first的数据
    if let firstObjects = object.objects(type: .first) {
        ForEach(firstObjects) { object in
            BarMark(
                x: .value("#", object.indexInSegment),
                y: .value("Distance", object.distance)
            )
            .foregroundStyle(by: .value("Type", object.type))
        }
    }
    
    // 处理Type.second的数据(即使为空也保留)
    if let secondObjects = object.objects(type: .second) {
        ForEach(secondObjects) { object in
            BarMark(
                x: .value("#", object.indexInSegment),
                y: .value("Distance", object.distance)
            )
            .foregroundStyle(by: .value("Type", object.type))
        }
    }
}
.chartLegend(position: .bottom, spacing: 8)
.chartForegroundStyleScale([
    Type.first: Color.pink,
    Type.second: Color.yellow
])
.frame(minHeight: 200)

方式二:添加透明占位标记(适用于某些case无数据的场景)

如果某个枚举case没有对应的数据,你可以添加一个透明的占位标记,让图表识别到这个类别:

Chart {
    // 现有数据渲染逻辑
    if let allObjects = object.objects(type: Type.first) {
        ForEach(allObjects) { object in
            BarMark(
                x: .value("#", object.indexInSegment),
                y: .value("Distance", object.distance)
            )
            .foregroundStyle(by: .value("Type", object.type))
        }
    }
    
    // 为所有枚举case添加透明占位
    Type.allCases.forEach { type in
        if object.objects(type: type)?.isEmpty ?? true {
            BarMark(
                x: .value("#", 0),
                y: .value("Distance", 0)
            )
            .foregroundStyle(by: .value("Type", type))
            .opacity(0) // 隐藏占位标记,不影响图表显示
        }
    }
}
.chartLegend(position: .bottom, spacing: 8)
.chartForegroundStyleScale([
    Type.first: Color.pink,
    Type.second: Color.yellow
])
.frame(minHeight: 200)

额外检查点

  • 确保foregroundStyle(by:)的标签(这里是"Type")保持一致,图表会用这个标签来关联图例和样式。
  • 如果你的图表中完全没有任何数据,图例也不会显示,所以要保证至少有一个case有数据,或者通过占位标记让图表识别所有类别。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 18:32:51