I looked at this answer, and it appears the response may be "you can't get there, from here," but I have to try...
I am building a dynamic SwiftUI Charts generator, and need to figure out how to create legends, on the fly.
The chartForegroundStyleScale decorator takes a KeyValuePair, as an initializer argument, but it appears as if KeyValuePair can only be built, using literals. I need to be able to build the legend programmatically (hopefully, without having to manually create the views by hand, which will work, but is a pain).
Here's the code I have now, which DOES NOT work:
/* ##################################################### */
/**
Returns a chart legend KeyValuePairs instance.
*/
var legend: KeyValuePairs<String, Color> {
var dictionaryLiterals = [(String, Color)]()
rows.forEach { $0.plottableData.forEach { dictionaryLiterals.append(($0.description, $0.color)) } }
var ret = KeyValuePairs<String, Color>()
dictionaryLiterals.forEach { ret.append($0) }
return ret
}
Can I get there, from here?
EDITED TO ADD: Yeah, I know that there's issues with the code, but I'll burn that bridge, when I get to it. The sample is good enough to show what I'm trying to do. If I can't get this working, I'll be building a view, instead, which will be a different operation, entirely.
This has been an issue for me for a while now but reading this thread, I followed @david suggestion of chartForegroundStyleScale(domain:mapping:).
This worked for me! (finally)
The first part uses computed properties to combine the categories and the colors into their own matching arrays.
let showRate: Bool
let showRetries: Bool
let rateLegend = ["Tx Rate": Color.blue.opacity(0.5), "Rx Rate": Color.gray.opacity(0.5)]
let retriesLegend = ["Tx Retry Ratio": Color.mint.opacity(0.7), "Rx Retry Ratio": Color.purple]
var categories: [String] {
var combinedCategories: [String] = []
if showRate { combinedCategories.append(contentsOf: rateLegend.keys) }
if showRetries { combinedCategories.append(contentsOf: retriesLegend.keys) }
return combinedCategories
}
var colors: [Color] {
var combinedColors: [Color] = []
if showRate { combinedColors.append(contentsOf: rateLegend.values) }
if showRetries { combinedColors.append(contentsOf: retriesLegend.values) }
return combinedColors
}
Then on the chart, the following modifier does the trick.
.chartForegroundStyleScale(domain: categories, mapping: { category in
if let index = categories.firstIndex(of: category) {
return colors[index]
} else {
return .clear
}
}
)