Swift Chart报错:结构体未遵循Plottable协议的排查求助
解决Swift Charts中自定义结构体未遵循Plottable协议的问题
首先明确:你误解了Plottable协议的用途——它不是让你的整个数据模型结构体直接遵循的,而是给单个用于绘图的「值类型」(比如X/Y轴的单个数值)设计的。你的InvestmentData是包含多个绘图字段的数据容器,正确的做法是保留Identifiable,移除Plottable协议,然后在Chart视图中指定具体字段作为绘图值。
步骤1:修正数据结构体定义
把Plottable从结构体的协议列表中移除,因为你的模型是数据载体,不是单个绘图值:
struct InvestmentData: Identifiable { var id: Int { year } let year: Int let principal: Double let withReinvestment: Double let withoutReinvestment: Double let profit: Double }
步骤2:正确使用Swift Charts绘图
在Chart视图中,通过LineMark/BarMark等标记,直接指定模型中的具体字段作为X/Y轴值——Int、Double这些类型默认已经遵循Plottable协议,不需要额外处理:
// 假设你有一个InvestmentData数组 let investmentDataArray: [InvestmentData] = [ InvestmentData(year: 2020, principal: 1000, withReinvestment: 1200, withoutReinvestment: 1150, profit: 200), InvestmentData(year: 2021, principal: 1000, withReinvestment: 1450, withoutReinvestment: 1300, profit: 450), // 更多数据... ] // 绘制图表 Chart(investmentDataArray) { data in LineMark( x: .value("年份", data.year), y: .value("复利收益", data.withReinvestment) ) .foregroundStyle(.blue) LineMark( x: .value("年份", data.year), y: .value("单利收益", data.withoutReinvestment) ) .foregroundStyle(.orange) }
为什么你之前的尝试没用?
- 移除
id和year:问题根源是误解了Plottable的用途,和这两个字段无关 - 给非Double类型写扩展:完全没必要,Int本身默认支持Plottable
- 把所有字段改成Double:整个模型不需要遵循Plottable,改类型解决不了核心问题
- 创建单变量结构体未生效:如果要让自定义类型遵循Plottable,必须实现协议要求的关联类型和方法,比如指定
PrimitivePlottable为对应的基础类型,返回primitivePlottableValue,而不是只加协议声明
特殊场景:让自定义类型作为绘图值(不推荐你的场景)
如果确实需要把整个InvestmentData作为单个绘图值(比如特殊的自定义轴),才需要完整实现Plottable协议:
struct InvestmentData: Identifiable, Plottable { var id: Int { year } let year: Int let principal: Double let withReinvestment: Double let withoutReinvestment: Double let profit: Double // 指定协议要求的关联类型,这里用year对应的Int作为绘图基础值 typealias PrimitivePlottable = Int // 返回用于绘图的原始值 var primitivePlottableValue: Int { year } // 实现从原始值初始化的方法(根据你的需求补充逻辑) init?(primitivePlottableValue: Int) { self.year = primitivePlottableValue // 这里需要补充其他字段的初始化逻辑,比如从数据源获取对应年份的数据 self.principal = 0.0 self.withReinvestment = 0.0 self.withoutReinvestment = 0.0 self.profit = 0.0 } }
但这种用法对你的场景完全没必要,因为你需要用模型中的多个数值绘制多条曲线,直接指定单个字段绘图才是正确方式。
内容的提问来源于stack exchange,提问作者Max
相关产品推荐
相关产品推荐

