Charts are broken with Xcode 27, Plotting multiple lines

Hi,

Charts—specifically those with multiple lines—are broken in Xcode 27.

First, I spotted the bug in my program, and then I checked your example.

Your own example Plotting-multiple-lines is not working correctly anymore. It shows 1 line or sometimes no lines at all, depending on the order of the data.

It depends on how the data is passed to the chart. If the data is passed as separate series, it works.

In Visualizing your app’s data it works, but the data is passed as described before.

Don't follow Microslop: have the AI ​​generate the code and then skip the tests.

This is a serious bug that requires a lot of work to rearrange the data, just to work around the issue.

Christian

Answered by DTS Engineer in 907742022

Please consider filing a bug report about this so our engineering teams can investigate this issue. A resolution may involve changes to Apple's software. If you post the Feedback number here I'll check the status next time I do a sweep of forums posts where I've suggested bug reports.

Bug Reporting: How and Why? has tips on creating your bug report.

When will there be a bug fix?

This works

var dataMultiLine: [LocationData.Series] {
    LocationData.last30Days
}

struct MultiLineView: View {
    var body: some View {
        VStack {
            Chart {
                ForEach(dataMultiLine) { series in
                    ForEach(series.sales, id: \.day) { element in
                        LineMark(
                            x: .value("Day", element.day, unit: .day),
                            y: .value("Sales", element.sales)
                        )
                    }
                    .foregroundStyle(by: .value("City", series.city))
                    .symbol(by: .value("City", series.city))
                    .interpolationMethod(.catmullRom)
                }
            }
        }
        .padding()
    }
}

This doesn't work

var dataContent: [MonthlyHoursOfSunshine] = [
    MonthlyHoursOfSunshine(city: "Cupertino", month: 1, hoursOfSunshine: 196),
    MonthlyHoursOfSunshine(city: "Seattle", month: 1, hoursOfSunshine: 74),
    MonthlyHoursOfSunshine(city: "Seattle", month: 12, hoursOfSunshine: 62),
    MonthlyHoursOfSunshine(city: "Cupertino", month: 12, hoursOfSunshine: 199),
]

struct ContentView: View {
    var body: some View {
        VStack {
            Chart(dataContent) {
                    LineMark(
                        x: .value("Month", $0.date),
                        y: .value("Hours of Sunshine", $0.hoursOfSunshine)
                    )
                    .foregroundStyle(by: .value("City", $0.city))
                    .symbol(by: .value("City", $0.city))
                }
        }
        .padding()
    }
}

Christian

Please consider filing a bug report about this so our engineering teams can investigate this issue. A resolution may involve changes to Apple's software. If you post the Feedback number here I'll check the status next time I do a sweep of forums posts where I've suggested bug reports.

Bug Reporting: How and Why? has tips on creating your bug report.

Hi,

thanks for the tip about the bug report. I thought the forum was also for reporting bugs.

The Bug Report number is FB25050954

Christian

Thanks for filing FB25050954 and for posting both versions of your chart. The Charts team has looked at the report.

The difference between your two versions is in the identifiers. I tested in macOS 27.0.1 and the iOS 27.0 simulator. When points in different cities share an id, a flat Chart(data) draws one line or none. An id based on the month or date causes this. In macOS 27.0.1, giving every data point its own id draws both lines from the same four points, in either order.

The init(_:content:) documentation says: "This initializer wraps the data that you provide as input in an implicit ForEach structure. If you need to represent more than one series in your chart, use init(content:) instead." Your nested ForEach version follows that route.

If you'd rather keep your existing flat array, an identifier change made it draw every line in my testing. Either of these gives each point its own identifier:

// One identifier for each city and month.
var id: String { "\(city)-\(date)" }

// A separate identity for every entry, even two entries with identical values.
let id = UUID()

A UUID identifier changes each time you create the array, so it suits data that keeps the same instances between updates.

If your MonthlyHoursOfSunshine already has an identifier that's unique for every data point and lines still go missing, please add that detail to FB25050954.

Hi,

as I already mentioned in my first post—including a link to the Apple website—the example is not my own code; it comes from Apple itself.

The example worked prior to version 27, which is why I formatted my data in exactly that way; it ran without any issues until version 27.

I have already structured my data differently, though I might adjust it again.

For now, however, I am occupied with other SwiftUI bugs—for instance, NavigationSplitView, endless loop detail<->content

Unfortunately, no one has responded to the post yet.

I wanted to wait for a response before submitting a bug report, in case the procedure I’m following is incorrect.

Christian

My first attempt using the ID didn't work, and the data continued to be displayed incorrectly. I’m not entirely sure what went wrong, so I tried again today.

With the unique ID, the data was displayed correctly. This can be achieved either by implementing the Identifiable protocol or by using the chart initializer that accepts both data and an ID.

struct MonthlyHoursOfSunshine: Identifiable {
        var city: String
        var date: Date
        var hoursOfSunshine: Double
        var monthlyId: UUID = UUID()
        
        init(city: String, month: Int, hoursOfSunshine: Double) {
            let calendar = Calendar.autoupdatingCurrent
            self.city = city
            self.date = calendar.date(from: DateComponents(year: 2020, month: month))!
            self.hoursOfSunshine = hoursOfSunshine
        }
        var id: UUID {
            monthlyId
        }
    }

However, as I mentioned earlier, the Apple example I initially used as a reference is now flawed; the data neither implements Identifiable nor uses the initializer that includes an ID.

Christian

Thanks for trying the identifier again and posting the version that works.

You're right that the code comes from our LineMark example. As written, its MonthlyHoursOfSunshine doesn't conform to Identifiable, which init(_:content:) requires, so anyone who uses the example has to choose an identifier. I've filed a documentation report about the example.

You're also right that version 27 changed what the example draws. I tested with an identifier based on the date. iPadOS 26.7 and the iOS 26.5 simulator draw both lines, and the iOS 27.0 simulator and macOS 27.0.1 draw one line. Your FB25050954 is the report for that change.

You can file a bug report about the problem in your NavigationSplitView thread before anyone replies there. You don't need to be sure the problem is in the framework. Include a small project that reproduces it, and post the FB number in that thread.