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