Ghostboard pixel

Swift: Using Local Closures

Swift: Using Local Closures

Closures are often used as function arguments. But sometimes there are situations where local closures can be very handy.


Hint: This post has been updated to Swift 3, iOS 10 and Xcode 8
Imagine you have a view controller that has two GUI modes:

enum GUIMode {
      case Mode1
      case Mode2
}

For each GUI mode you want to set some properties for three labels:

var guiMode: GUIMode = .Mode1 {
    didSet {
        switch guiMode {
        case .Mode1:
            label1.text = "1"
            label1.textColor = UIColor.red
            label1.font = UIFont(name: "HelveticaNeue", size: 10)
        
            label2.text = "2"
            label2.textColor = UIColor.blue
            label2.font = UIFont(name: "HelveticaNeue", size: 12)
        
            label3.text = "3"
            label3.textColor = UIColor.yellow
            label3.font = UIFont(name: "HelveticaNeue", size: 11)
        
        case .Mode2:
            label1.text = "4"
            label1.textColor = UIColor.yellow
            label1.font = UIFont(name: "HelveticaNeue", size: 11)
        
            label2.text = "5"
            label2.textColor = UIColor.blue
            label2.font = UIFont(name: "HelveticaNeue", size: 9)
        
            label3.text = "6"
            label3.textColor = UIColor.brown
            label3.font = UIFont(name: "HelveticaNeue", size: 10)
        }
    }
}

This is a lot of code. You could create a function that sets the properties for a label, but it is very unlikely that you will use that function ever again. So in this case it is a nice solution to define a local closure within the function:

var guiMode: GUIMode = .Mode1 {
    didSet {
        let styleLabel: (_ label:UILabel,_ text:String,_ color:UIColor,_ size:CGFloat) -> () = { (label,text,color,size) in
            
            label.text = text
            label.textColor = color
            label.font = UIFont(name: "HelveticaNeue", size:size)
        }
    
        switch guiMode {
        case .Mode1:
            styleLabel(label1, "1", UIColor.red, 10)
            styleLabel(label2, "2", UIColor.blue, 12)
            styleLabel(label3, "3", UIColor.yellow, 11)
        case .Mode2:
            styleLabel(label1, "4", UIColor.yellow, 11)
            styleLabel(label2, "5", UIColor.black, 9)
            styleLabel(label3, "6", UIColor.brown, 10)
        }
    }
}

It is short and it is nice.

References

Image: @ Sergey Nivens / shutterstock.com