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