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 Type {
    case SoldOut 
    case Expired
  }
  
  init(type: Type) {
    super.init(frame: .zero)
    
    font = UIFont.commonFont()
    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             = .SoldOutLabel
  backgroundColor = .blackColor()
  textColor       = .whiteColor()
case .Expired:
  tag             = .ExpiredLabel
  backgroundColor = .whiteColor()
  textColor       = .redColor()
}

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) = { _ -> (ViewTag, UIColor, UIColor) in
  switch type {
  case .SoldOut: return (.SoldOutLabel, .blackColor(), .whileColor()
  case .Expired: return (.ExpiredLabel, .whiteColor(), .redColor())
  }
}

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.