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. โค๏ธ๐Ÿค–