Struct doesn't conform to protocol Plottable

69 Views Asked by At

I'm attempting to make Swift Chart to work. I have this struct that Xcode says doesn't conform to Plottable. I checked protocol spec and it expect Double, String or Date. Id and Year therefore do not conform. The problem is that even when remove id and year from the struct, Xcode continues to say it doesn't conform to Plottable, and I have no idea why. Hours of searching, trying, and I couldn't make it work.

struct InvestmentData: Identifiable, Plottable {
    var id: Int { year }
    let year: Int
    let principal: Double
    let withReinvestment: Double
    let withoutReinvestment: Double
    let profit: Double
}

Xcode suggests adding protocol stubs, but I have no idea what to do with it.

typealias PrimitivePlottable = <#type#>

I would appreciate any pointers.

Tried:

  1. Removing id and year altogether
  2. Tried writing extension for non-Doubles, but couldn't make it work
  3. Tried changing everything to Double - still says doesn't conform
  4. Tried making new struct with just one var - it doesn't conform either
2

There are 2 best solutions below

1
Joakim Danielson On BEST ANSWER

Do you really need to use Plottable in your implementation? The struct can be used directly in a chart

Chart(data) {
    BarMark(
        x: .value("Year", $0.year),
        y: .value("Profit", $0.profit)
    )
}

Although it will look much better with a String as the x value type

extension InvestmentData {
    var yearLabel: String {
        "\(year)"
    }
}
Chart(data) {
    BarMark(
        x: .value("Year", $0.yearLabel),
        y: .value("Profit", $0.profit)
    )
}
2
Rob Napier On

A Plottable is something that can be turned directly into a PlottableValue. It needs to have a number, string, or date value that would be plotted in all cases. A multi-value struct is rarely what you mean. If I plotted an InvestmentData (.value("MyInvestment", investment)), what height would it go at in a bar chart? The principal? The profit? An Investment is not a "value" in this sense.

The autocorrection from Xcode is unfortunate. You didn't need to add PrimitivePlottable as a typealias. You need to implement the required methods. PrimitivePlottable is the type of the underlying thing you're going to plot, and is inferred from your methods.

The following probably isn't useful, but demonstrates how to implement it:

extension InvestmentData: Plottable {
    var primitivePlottable: Int { year  }
    init?(primitivePlottable: Int) {
        // This probably doesn't make sense, but is the best we can
        // do here.
        return nil
    }
}