I like to use colors as variables/constants like Color(.primaryColor)
instead of text names like Color("primary_color")
. It's faster, there's less chance of making a mistake, and you can quickly refactor by renaming the color name globally throughout the code.
Going through possible solutions to make it easier to work with colors, I decided that I dоn't want to use Swift R for this purpose for a number of reasons. I also don't plan to use Storyboard or Xib files. So, I decided to store colors in code.
But I ran into a problem; I couldn't find a standard easy way to create a dynamic color using code that will change automatically depending on the current color scheme in real-time.
Later, I found a mechanism in UIColor that allows me to do the intended thing, and I made an initializer based on it.
An initializer accepting colors as UIColor would be handy for concise writing with color literals:
extension Color {
init(_ unspecifiedColor: UIColor,
dark darkColor: UIColor,
light lightColor: UIColor? = nil) {
self = Color(UIColor {
switch $0.userInterfaceStyle {
case .unspecified:
return unspecifiedColor
case .dark:
return darkColor
case .light:
return lightColor ?? unspecifiedColor
@unknown default:
return unspecifiedColor
}
})
}
}
Example of use with color literals:
extension Color {
// Instead of a 🟩 & 🟥 use something like this:
// #colorLiteral(red: 0, green: 1, blue: 0, alpha: 1).
// Commenting code with ``//``
// will switch between ``🟩`` & ``#colorLiteral(...)``.
static let primaryColor = Color(🟩, dark: 🟥)
}
An initializer accepting colors as SwiftUI.Color will probably come in handy too:
extension Color {
init(_ unspecifiedColor: Color,
dark darkColor: Color,
light lightColor: Color? = nil) {
let lightUIColor = lightColor.map { UIColor($0) }
self.init(UIColor(unspecifiedColor),
dark: UIColor(darkColor),
light: lightUIColor)
}
}
Example of use with constants:
extension Color {
static let primaryColor = Color(.red, dark: .blue)
}
Whole demo app:
extension Color {
static let primaryColor = Color(🟩, dark: 🟥)
}
@main
struct DynamicColorApp: App {
@State var colorSheme: ColorScheme = .light
var body: some Scene {
WindowGroup {
VStack {
Text("Green by day and red by night")
.foregroundColor(.primaryColor)
Button("light") {
colorSheme = .light
}
Button("dark") {
colorSheme = .dark
}
}
.preferredColorScheme(colorSheme)
}
}
}
Result:
I will be glad to answer your comments if you have any remarks or ideas about it.
Thank you for your attention. ❤️🤖