Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Creating a Binding to a computed var called Color for ColorPicker

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?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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
    }
}

>Solution :

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

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading