Creating a theme helper

:  ~ 1 min read

The standard approach for this would be something like this:

struct Theme {
  enum Color {
    case Title, Subtitle, ...
    
    // The usual approach is with a function, but a computed property is also an alternative
    var color: UIColor {
      switch self {
      case .Title: return UIColor.redColor()
      case .Subtitle: return UIColor.blueColor()
      ...
      }
    }
  }
  enum Font {
  }
}

And using it throughout the app would look like this:

func customLabel(text text: String, textColor: Theme.Color, textFont: Theme.Font) {
  [...]
  label.textColor = textColor.color
  label.font = textFont.font
  [...]
}

let myLabel = customLabel(
  text: "Pretty label", 
  textColor: .Title, 
  textFont: .Title
)
myLabel.textColor = Theme.Color.Subtitle.color
myLabel.font = Theme.Font.Subtitle.font

Another approach would be with nested structs and static constants for avoiding the color / font computed property (at the cost of slight, but unnecessary extra memory usage):

struct Theme {
  struct Color {
    static let title = UIColor.redColor()
    static let subtitle = UIColor.blueColor()
    ...
  }
}

I find this approach pretty neat, but I'm not really sold vs simple extensions:

extension UIColor {
  static func titleColor() -> UIColor { return UIColor.redColor() }
  static func subtitleColor() -> UIColor { return UIColor.blueColor() }
  ...
}
extension UIFont {
  ...
}

And the usage would be the one we're all already familiar with, which involves a lot less typing, too:

func customLabel(text text: String, textColor: UIColor, textFont: UIFont) {
  [...]
  label.textColor = textColor
  label.font = textFont
  [...]
}

let myLabel = customLabel(
  text: "Pretty label", 
  textColor: .titleColor(), // This is OK
  textFont: .titleFont()
)
myLabel.textColor = .subtitleColor() // This is also OK
myLabel.font = .subtitleFont()