Edward Loveall

Swift Configuration Objects

I’m working on a project that requires drawing some boxes on the screen. The boxes all behave the same way, but some have different sizes and colors.

To keep track of these sizes, colors, and potentially other settings, I’ve built a Style struct to namespace and organize all variables in one place. A codified Style Guide if you will. Here’s what it looks like:

struct Style {
  static let colors = (
    red: NSColor(red: 0.93, green: 0.47, blue: 0.45, alpha: 1.0),
    green: NSColor(red: 0.65, green: 0.89, blue: 0.67, alpha: 1.0)
  )

  static let sizes = (
    small: CGSize(width: 10, height: 10),
    medium: CGSize(width: 30, height: 30)
  )
}

This lets me use these sizes and colors like so:

let red = Style.colors.red
let small = Style.sizes.small

Since the constants are tuples, you could, in theory, group the variables by the objects they’ll be used in:

struct Style {
  static let boxA = (
    color: NSColor(red: 0.93, green: 0.47, blue: 0.45, alpha: 1.0),
    size: CGSize(width: 10, height: 10)
  )

  static let boxB = (
    color: NSColor(red: 0.65, green: 0.89, blue: 0.67, alpha: 1.0),
    size: CGSize(width: 30, height: 30)
  )
}

If this is what you want, I’d suggest an alternative: group them first by their type (size, color, etc.), then use those constants to define other groupings:

struct Style {
  static let colors = (
    red: NSColor(red: 0.93, green: 0.47, blue: 0.45, alpha: 1.0),
    green: NSColor(red: 0.65, green: 0.89, blue: 0.67, alpha: 1.0)
  )

  static let sizes = (
    small: CGSize(width: 10, height: 10),
    medium: CGSize(width: 30, height: 30)
  )

  static let boxA = (
    color: Style.colors.red,
    size: Style.sizes.small
  )

  static let boxB = (
    color: Style.colors.green,
    size: Style.sizes.medium
  )
}

It feels a little awkward to be referencing the struct inside of itself, but the tradeoffs seems worth it. If you apply red to other properties, (like a stroke color, for example) you can:

This pattern seems useful in projects where a designer has created a formal style guide. This is opposed to having loose-leaf constants scattered about the code, or even collected at the top of a single file.

I’d love to know what you think about it. How do you think it could improve? What other use cases you see it having?

Update

Davide De Franceschi pointed out to me that just by using an enum instead of a struct, I remove the ability to instanciate a Style, which is a good thing.

He also pointed out that I can use enums all the way down:

enum Style {
  enum Colors {
    static let red = NSColor(red: 0.93, green: 0.47, blue: 0.45, alpha: 1.0)
    static let green = NSColor(red: 0.65, green: 0.89, blue: 0.67, alpha: 1.0)
  }

  enum Sizes {
    static let small = CGSize(width: 10, height: 10)
    static let medium = CGSize(width: 30, height: 30)
  }
}

Nice!