Hop on the waitlist to be the first to get the book. I'm in.
I've found so many articles and video introductions to Swift Charts, and almost all have been helpful, some extremely helpful. But what I've yet to find is an article that goes well beyond the basics, something that could help me build not just a chart... but a charting system that could be embedded within my App. A system that would consistently produce nice visual charts with all the accouterments like labeled axis values with grid lines where appropriate.
See Also - the Basics...
When I first started with the iOS 16 beta Charts framework... not even Apple had any GOOD documents... that's changed a bit. But for the life in me... I cannot turn their docs into compiling functional code. So I turn to the Fab Four: Hacking With Swift, Stewart Lynch, Sean Allen, and Chris.
Rendering Charts in SwiftUI - by Paul (Hacking with Swift) https://www.hackingwithswift.com/plus/rendering-charts-in-swiftui
SwiftUI Pie & Donut Charts - New in iOS 17 by Sean Allen https://www.youtube.com/watch?v=8M3N4HWUc0U
Charts Framework in SwiftUI by Stewart Lynch https://www.youtube.com/watch?v=csd7pyfEXgw
SwiftUI Charts Basics Tutorial by Code With Chris https://www.youtube.com/watch?v=MyQy1E-bzEM
There are many others...
https://github.com/jordibruin/Swift-Charts-Examples
I'm going to start this VIBE Blogging post... right here - right now... it is NOT the article you are looking for...
Maybe one day in a far far future...
If you came here looking for a better Charts framework... not going to build it. If you are frustrated with the lack of good how to do Charts properly... wait on Big Mountain Studio.
This is my wish list for a how to do charts. It might contain some resources... it might contain some lies or AI hallucinations or maybe a true fact.
A List of Needs:
Rounding Numbers
Heuristic for Axis Labels
Legend
Grid Lines and Axis tick marks
How to handle date values and properly display axis labels
Rounding Numbers to good values.
If you have played around with Swift Charts for any time, you will know it can provide you with default Axis values and labels. But, will these values be good human understandable values... maybe not.
The goto standard for "nice" round numbers is in a book in the library; The Graphics Gems Series by Andrew Glassner (1990). Since you and I are too cheap to buy the book... go to this Stack Overflow page to get the algorithm in many various programming languages.
Don't just use the first one you find - test it first.
In the StackOverflow article: Styling chart axes
We find a nice heuristic for Swift Chart Labels. "Sweeper" suggests a 3 layer approach for AxisMarks that seems to be well conceived. 1 - AxisMarks for major number values (every one in the example); 2 - AxisMarks for minor grid lines or minor tick marks; 3 - AxisMarks for the outter bounds (the bottom gridline). The Tick marks are offset so as to cross the axis lines.
This has been the BEST example of explaining the configuration of an axis that I've found.
An Example Y Axis Label set:
.chartYAxisLabel(position: .leading, alignment: .center) { Text("Y Label") }
.chartYScale(domain: [-2, 2])
.chartYAxis {
AxisMarks(position: .leading, values: .stride(by: 1)) {
AxisValueLabel()
}
AxisMarks(position: .leading, values: .stride(by: 0.2)) { value in
if value.index != 0 { // the bottommost value does not need a tick
AxisTick(length: 8, stroke: .init(lineWidth: 1))
.offset(x: 4)
}
}
AxisMarks(position: .leading, values: [-2]) {
AxisGridLine(stroke: .init(lineWidth: 1))
}
}
The reason we are all here... it is not because someone caught Mr Mustard in the act with the candlestick over Mr. Body. It is the data - Smarty... we want to see the data. And if you already have the data then start with it.
But many times the App's data must be manipulated and formatted to look well presented in a chart. So you may want to extract the App's data into a specific Chart ViewModel. I've not seen this advice in the videos and articles... but it seems like a good thing(TM).
I've wondered how to do this extraction on real-life data... and Swift has several tools that come to mind. Array Slices is one tool. When charting the stock earnings and dividends I didn't want to show years of data - just the last 2 years of quarterly dividends. So an Array Slice of 8 was required.
var divArraySlice: [Dividend] = []
divArraySlice = Array(fullArray.prefix(8)) // <=== EIGHT points
The prefix() function returns a Subsequence type. Therefore a need to wrap it in an Array() to get back to an array of Dividends that can be handed off to the Chart().
There is quite a lot of data processing that must be done and charting will help you find out what is missing. For example, with my array of Dividends, I needed a sort operation to get them sequenced in chronological order.
// Add computed property to sort dividends by Ex Dividend Date descending
var sortedDividends: [Dividend] {
dividendList?.sorted { first, second in
guard let date1 = first.exDividendDate,
let date2 = second.exDividendDate else {
return false
}
return date1 > date2 // Sort descending (newest first)
} ?? [] // or empty list
}
Yet that is not the order I wanted the Dividends to be plotted. The order is reversed - so that the newest dividend is on the rightmost of the chart.
GroupBox("Dividends") {
Chart(data.reversed() ) {
// flow data from old date to -> new date on x-axis
This is where the Apple docs have a good set of examples... go look. I counted 32 ChartContent modifiers... lots to choose from. Adding any of a number of modifiers to the content will brighten and color your chart.
I've been struggling all morning trying to get a Chart Legend to show up in an example chart... no luck...
Then I find a StackOverflow that appers to suggest that adding a
ForegroundStyleScale array will fix it. And it does.
The "Any Junk text" never displays but the Legend pops into vision. It is all wonky and thats not 4 points of spacing... but visible is good.
Why would a mapping of key value pairs turn on the Legend visibility?
Seems like a bug to me.
Examining what I did, I mapped a text value to the color green in a Dictionary passed to a Style SCALE? WTF!
FB17044094
Chart Legend not visible until adding .chartForegroundStyleScale
When I started messing with Charts I noticed all this extra data about the chart. We can either hardcode it... or hope there is a smart configuration that works most of the time... I've heard it said - hope is not a strategy!
So I'm looking for a strategy to deal with all the configuration data about the charts... there is a tooling gap here. And all the beginning tutorials ignore it... and there are not any advanced Swift Chart articles...
Some ideas: Could one extend the Chart struct to allow a newly passed in configuration struct? No, extending in Swift land does not allow new initializers. Nor does an extension allow storing new properties.
So that idea is kind of busted... But I could create a new Chart_configuration Struct with all the needed metadata. And every time I've started working on this... I get so wrapped up in all the variations it never gets to working code... so I'm not going down that rabbit hole AGAIN! The answer is to bite off just a small but useful chunk. That was the Chart Legend... and look at the rabbit hole I just came out of... OUCH!
But there it is working out. The ChartLegend_Config() struct with all the Legend metadata assigned to the proper Chart functions. And the hack to make Legends visible in the code. The title displays in the iOS simulator in BLUE for some reason. More work to figure that blue text out. Let's work on the axis config! The proof is working.
As a proof of concept I wrote this set of Chart configuration structures that just define the most used option/values for Charts. Then I have a template to define all these various pieces of meta data to configure a typical chart.
Still it from this GitHub Gist: ExampleConfigChart.swift
And let me know how to improve it.
What's next?