Setting variables with tuples, switches and closures

:  ~ 1 min read

Let's say we have a custom UILabel, which in turn has several types; maybe a StatusLabel that can be of type sold out and expired. The label would have several common properties, but each type would have something specific. How can we go about this?

class StatusLabel: UILabel {
  enum StatusType {
    case soldOut 
    case expired
  }
  
  init(type: StatusType) {
    super.init(frame: .zero)
    
    font = UIFont.common
    layer.cornerRadius = 4
    textAlignment = .center
    translatesAutoresizingMaskIntoConstraints = false
  }
}

We now covered the common parts, and we could go ahead and set the backgroundColor and textColor like this:

switch type {
case .soldOut:
  tag             = ViewTag.soldOutLabel.rawValue
  backgroundColor = .black
  textColor       = .white
case .expired:
  tag             = ViewTag.expiredLabel.rawValue
  backgroundColor = .white
  textColor       = .red
}

Nothing too ugly so far, but it's already clear that if we'll need to add more cases in the future, the amount of code will drastically increase. Instead, we can make use of tuples and closures:

(tag, backgroundColor, textColor) = { _ -> (Int, UIColor, UIColor) in
  switch type {
  case .soldOut: return (ViewTag.soldOutLabel.rawValue, .black, .white
  case .expired: return (ViewTag.expiredLabel.rawValue, .white, .red)
  }
}

A bit more compact, and easier to scan columns for the differences. On the other hand, it's also clear that if there are too many different properties between different types, or if 4/5 types have one value for a property, but the 5th is different, this approach stops being as elegant or feasible.