Persistence pays off.
NOTE
This blog entry has been sitting in my drafts for months and it’s quite likely that the answers I received from AI would likely be different now.
Intro
Swift Charts is fantastic and I make extensive use of it in Please Don’t Rain. But when charts don’t act as you would expect it can be extremely challenging trying to find a solution. I want to describe an issue I was having and the solution I arrived at. Hopefully this will save someone some time.
There’s something that’s been bothering me with my LineMark charts for the entire time my app has existed. If you looked closely at the Y Axis labels on my charts, the chart would start a little after 12AM and end a little before 12AM for the following day.
The chart starting a little after 12AM. The chart stopping a little before 12AM the next day.
The chart is based on data from WeatherKit. It sends hourly data for each hour starting at the top of the hour. At first I thought the alignment problem was because my hourly data for a day would actually end at 11PM. That’s because I was only including hourly data (24 entries total) for “today” and 12AM on the following day is data for another day. That would explain why the chart ended early but it wouldn’t explain why the chart didn’t align with the LineMark for the start of the day at 12AM.
I looked through the Apple documentation, Apple developer forums, Jordi’s open source Swift Charts sample project, and various other search results but couldn’t find anything that ended up being helpful.
I tried questioning Claude, ChatGPT, and Perplexity and got these various answers:
Attempt 1
- Double check that your data starts at 12am
I knew this couldn’t be it because I was positive my data was accurate.
Attempt 2
- .chartXScale(domain: start…end)
This didn’t change anything.
Attempt 3
- Add .position(by: .value(“Hour”, date, unit: .hour, calendar: calToUse))
This one actually seemed to help a little. But it just reduced the unwanted offset of my LineMark. It didn’t get rid of it.
Attempt 4
- A suggestion was to try removing all AxisMarks and use AxisMarks(values .automatic) to see if the problem still took place.
It did.
Attempt 5
- Adjust your data points to force alignment date.addingTimeInterval(-0.1)
This was the most “out there” solution and I was very resistant to doing it.
Stack Overflow To The Rescue
After spending time experimenting with all of these with no success I refused to give up and started poring through search results again. I was looking at a Stack Overflow post when this particular comment (with only two upvotes 🤨) written by Sweeper caught my eye:
Wait a minute! I was indeed specifying a unit for my chart.
LineMark(
x: .value("Hour", oneChartData.date, unit: .hour, calendar: calToUse),
y: .value("UV Index", uvIndex.value)
)
Having the plot be in the halfway point is ideal for my bar chart (precipitation) but could that be what was causing my problem with my other charts that aren’t bar charts?
I took out unit: and calendar: and look what happened. My chart suddenly was aligned with the Y axis mark.
I never in a million years would have thought of this solution because my app is often used to track weather in a different time zone and I would have thought specifying the calendar for LineMark was critical. But it appears that specifying the calendar in just the AxisMarks call is sufficient.
AxisMarks(values: .stride(by: .hour, count: 4, calendar: calToUse)) { _ in
Hopefully this post will prevent someone from spending as much time on this as I did!
Big thanks to Sweeper for writing that Stack Overflow post!
Contact
If this post was helpful to you I’d love to hear about it! I’m @chriswu.com on Bluesky, @MuseumShuffle@mastodon.social on Mastodon, and my email is museumshuffle at gmail dot com.
CommunityKit
I’m one of the people organizing a new FREE event called CommunityKit for WWDC25. We’d love to have you there!
If you’re in town for WWDC25, you’re welcome at CommunityKit – we’ll be hosting meetups, workshops, hackathons, and more, so that everyone can come and meet like-minded developers in the heart of Cupertino.