So basically I have an array of Themes and one attribute of a Theme is RGBAColor, which is basically 4 doubles. I'm intentionally not storing a Color struct because I don't want UI stuff like Colors to be in my model, which is UI independent. In my ViewModel, I "interpret" this RGBAColor to a normal Color struct.
I want the user to be able to change the color attribute of a theme through color picker, but since colorpicker takes in a binding to a color and not an RGBAColor, I'm in a bit of trouble. I was told that a hint is to create a binding to a computed var, so I made one
extension Theme {
var color: Binding<Color> {
Binding {
return Color(rgbaColor: self.rgbaColor)
} set: { newRGBAColor in
self.rgbaColor = RGBAColor(color: newRGBAColor)
}
}
}
but this doesn't work because self is immutable. How can I fix this?
struct ThemeEditor: View {
@Binding var theme: Theme
var colorSection: some View {
Section(header: Text("Colors")) {
VStack {
ColorPicker("Selection", selection: $theme.color)
}
}
}
}
struct RGBAColor: Codable, Equatable, Hashable {
let red: Double
let green: Double
let blue: Double
let alpha: Double
}
extension RGBAColor {
init(color: Color) {
var red: CGFloat = 0
var green: CGFloat = 0
var blue: CGFloat = 0
var alpha: CGFloat = 0
if let cgColor = color.cgColor {
UIColor(cgColor: cgColor).getRed(&red, green: &green, blue: &blue, alpha: &alpha)
}
self.init(red: Double(red), green: Double(green), blue: Double(blue), alpha: Double(alpha))
}
init(_ red: Double, _ green: Double, _ blue: Double, _ alpha: Double) {
self.init(red: red/255, green: green/255 , blue: blue/255, alpha: alpha)
}
}
extension Color {
init(rgbaColor rgba: RGBAColor) {
self.init(.sRGB, red: rgba.red, green: rgba.green, blue: rgba.blue, opacity: rgba.alpha)
}
}
struct Theme: Identifiable, Codable, Hashable {
var name: String
var emojis: String
var id: Int
var numberOfPairsOfCards: Int
var rgbaColor: RGBAColor
fileprivate init(name: String, emojis: String, id: Int, numberOfPairsOfCards: Int, rgbaColor: RGBAColor) {
self.name = name
self.emojis = emojis
self.id = id
self.numberOfPairsOfCards = numberOfPairsOfCards
self.rgbaColor = rgbaColor
}
}
CodePudding user response:
You just need to put it in view, like
struct ThemeEditor: View {
@Binding var theme: Theme
var color: Binding<Color> { // << here !!
Binding {
return Color(rgbaColor: theme.rgbaColor)
} set: { newRGBAColor in
theme.rgbaColor = RGBAColor(color: newRGBAColor)
}
}
var colorSection: some View {
Section(header: Text("Colors")) {
VStack {
ColorPicker("Selection", selection: self.color) // << here !!
}
}
}
// ...
}
Tested with Xcode 13.4