Example in Charts documentation does not work as shown.

Summary: The "ProfitOverTime" example code from https://developer.apple.com/documentation/charts/chart does not compile, and when changes are made to make it compile the chart concatenates the lines rather than having them be separate.

Seen in Xcode-Beta's 14.3 and 14. 4 (14A5284g)

Is it simply that this method of layering lines is deprecated already?


When trying to have a chart with multiple data sets, I copy-pasted the code from the above link and generated the appropriate placeholder data. I got an error that ProfitOverTime was not identifiable, so I added the id on date.

In both the case of the years being identical and of the years being different the lines concatenate instead of overlay like in the screenshot on the docs page.

Is this method of multiple lines still available and I'm just doing it wrong?

Is only method to have multiple lines series as seen on the LineMark docs page?

struct ChartTests: View {
    struct ProfitOverTime {
        var date: Date
        var profit: Double
    }

    static func months(forYear year:Int) -> [Date] {
        var days:[Date] = []
        var dateComponets = DateComponents()
        //let year = Calendar.current.component(.year, from: Date())
        dateComponets.year = year
        dateComponets.day = 1
        for i in 1...12 {
            dateComponets.month = i
            if let date = Calendar.current.date(from: dateComponets) {
                days.append(date)
            }
        }
        return days
    }

    static func dataBuilder(forYear year:Int) -> [ProfitOverTime]{
        var data:[ProfitOverTime] = []
        for month in months(forYear: year) {
            let new = ProfitOverTime(date: month, profit: Double.random(in: 200...600))
            data.append(new)
        }
        return data
    }

    let departmentAProfit: [ProfitOverTime] = Self.dataBuilder(forYear: 2021)
    let departmentBProfit: [ProfitOverTime] = Self.dataBuilder(forYear: 2021)

    var body: some View {
        Chart {
            ForEach(departmentAProfit, id: \.date) {
                LineMark(
                    x: .value("Date", $0.date),
                    y: .value("Profit A", $0.profit)
                )
                .foregroundStyle(.blue)
            }

            ForEach(departmentBProfit, id: \.date) {
                LineMark(
                    x: .value("Date", $0.date),
                    y: .value("Profit B", $0.profit)
                )
                .foregroundStyle(.green)
            }
            RuleMark(
                y: .value("Threshold", 500.0)
            )
            .foregroundStyle(.red)
        }
    }
}

struct ChartTests_Previews: PreviewProvider {
    static var previews: some View {
        ChartTests()
    }
}

Answered by rayfix in 723732022

Your LineMark is missing series. I think if you put that in it will break it into multiple plots like you want.

FWIW, why I care is this project - I want my recommended curve and edited curve to both be displayed. https://github.com/carlynorama/DataViewer/blob/main/DataViewer/DisplayView.swift

Also, conforming the struct ProfitOverTime to Identifiable by adding an id = UUID() has the same result

Feedback Assistant No: FB11061755

Accepted Answer

Your LineMark is missing series. I think if you put that in it will break it into multiple plots like you want.

Example code that works from the updated page

(I should add that this code leaves in the fact that I made ProfitOverTime conform to Identifiable and the new code on the documentation page uses ForEach(departmentAProfit, id: \.date) instead.)

import SwiftUI
import Charts

struct ChartTests: View {
    struct ProfitOverTime:Identifiable {
        var date: Date
        var profit: Double
        var id = UUID()
    }

    static func months(forYear year:Int) -> [Date] {
        var days:[Date] = []
        var dateComponets = DateComponents()
        //let year = Calendar.current.component(.year, from: Date())
        dateComponets.year = year
        dateComponets.day = 1
        for i in 1...12 {
            dateComponets.month = i
            if let date = Calendar.current.date(from: dateComponets) {
                days.append(date)
            }
        }
        return days
    }

    static func dataBuilder(forYear year:Int) -> [ProfitOverTime]{
        var data:[ProfitOverTime] = []
        for month in months(forYear: year) {
            let new = ProfitOverTime(date: month, profit: Double.random(in: 200...600))
            data.append(new)
        }
        return data
    }

    let departmentAProfit: [ProfitOverTime] = Self.dataBuilder(forYear: 2021)
    let departmentBProfit: [ProfitOverTime] = Self.dataBuilder(forYear: 2021)

    var body: some View {
        Chart {
            ForEach(departmentAProfit) {
                LineMark(
                    x: .value("Date", $0.date),
                    y: .value("Profit A", $0.profit),
                    series: .value("Company", "A")
                )
                .foregroundStyle(.blue)
            }

            ForEach(departmentBProfit) {
                LineMark(
                    x: .value("Date", $0.date),
                    y: .value("Profit B", $0.profit),
                    series: .value("Company", "B")
                )
                .foregroundStyle(.green)
            }
            RuleMark(
                y: .value("Threshold", 500.0)
            )
            .foregroundStyle(.red)
        }
    }
}

struct ChartTests_Previews: PreviewProvider {
    static var previews: some View {
        ChartTests()
    }
}

Screenshot

:

Example in Charts documentation does not work as shown.
 
 
Q