Help me make my code "DRY"

struct ColorPallet: View {
    struct NameColor: Hashable {
        let name: String
        let color: Color

        init(_ name: String, _ color: Color) {
            self.name = name
            self.color = color
        }
    }

    let colors = [
        NameColor("systemGray", Color(UIColor.systemGray)),
        NameColor("systemGray2", Color(UIColor.systemGray2)),
        NameColor("systemGray3", Color(UIColor.systemGray3)),
        NameColor("systemGray4", Color(UIColor.systemGray4)),
        NameColor("systemGray5", Color(UIColor.systemGray5)),
        NameColor("systemGray6", Color(UIColor.systemGray6)),
        NameColor("systemFill", Color(UIColor.systemFill)),
        // etc etc continue long list
    ]

    var body: some View {
        List(colors, id: \.self) {nameColor in
            ZStack {
                nameColor.color
                Text(nameColor.name)
            }
        }
    }
}

For the colors array, instead of storing both the string name and the color value, is there anyway I can just have one value and derive the name and color from it? KeyPath is no good here because the UIColor.systemXXX are static property. Mirror doesn't seem to work for the same reason...

You can use Obj-c selectors for that

struct ColorPallet: View {
    struct NameColor: Hashable {
        let name: String
        let color: Color

        init(_ name: String, _ color: Color) {
            self.name = name
            self.color = color
        }

        init(selector: Selector) {
            let color = UIColor.self.perform(selector)?.takeRetainedValue() as! UIColor
            self.color = Color(color)
            self.name = selector.description
        }
    }

    let colors = [
        NameColor(selector: #selector(getter: UIColor.systemGray)),
        NameColor(selector: #selector(getter: UIColor.systemBlue)),
    ]

    var body: some View {
        List(colors, id: \.self) {nameColor in
            ZStack {
                nameColor.color
                Text(nameColor.name)
            }
        }
    }
}
1 Like