In this tutorial you will learn about the Swift Closures and its application with practical example.
Swift Closures
Closures are anonymous functions consists of self-contained blocks of code and that can passed around in our code as a function parameters.In swift, we can assign closure references to constants or variables, later we can access or retrieve the value of closure based on our requirements.
Closures are like functions but they do not have name associated with it.Generally swift functions are considered as a special kind of closures and closures can take any one of three form –
Global functions :- These are closure having a name and cannot capture any values.
Nested functions :- These are closure having a name and can capture values from their enclosing functions
Closure expressions :- These are closure having a name and can capture values from their context
Declaring a closure
In Swift, there are two ways we can define a closure.
Closure expressions –
In this method a closure is defined using curly brackets { } followed by parameters of the closure wrapped in a pair of parentheses, separated from the return type by the -> symbol and in keyword separate the closure header from closure body.
Syntax:-
1 2 3 |
{ (parameter_list) -> return_type in statements } |
In case closure does not return any value we can omit the arrow (->) and the return type as following –
Syntax:-
1 2 3 |
{ (parameter_list) in statements } |
Example:-
1 2 3 4 |
let helloClosure = { (name:String) -> () in print(name) } helloClosure("Hello, World!") |
Output:-
1 |
Hello, World! |
Trailing Closure –
If the last parameter of a function is a closure, then we can put closure definition directly after the function call instead passing it as a function parameter. It is termed as trailing closures.
Example:-
1 2 3 4 5 6 7 8 |
func sayHello(msg:String, helloClosure:()->()) { print(msg) helloClosure() } print("W3Adda - Trailing Closure.") sayHello(msg:"Hello from function.") { print("Hello from closure.") } |
Output:-
Swift Closures Type Inferring
In Swift, type inference allows to infer the return type from the context in which the closure is defined so we can remove (->) sign and return type to create short form of using closures in swift.
Example:-
1 2 3 4 5 6 |
var sum = {(a: Int, b: Int) in return a + b } let result = sum (10,25) print("W3Adda - Closure Type Inference.") print(result) |
Output:-
Swift Closures with Implicit Returns
If closures body contains only one statement which return the result in that statement, so we choice to omit the return keyword.
Example:-
1 2 3 4 5 6 |
var sum = {(a: Int, b: Int) in a + b } let result = sum (10,25) print("W3Adda - Closure Implicit Return.") print(result) |
Output:-
Swift Shorthand Parameter Names
Swift provides a shorthand method to access the closures parameters, in which it provides a list of shorthand names for parameters.In order to use shorthand parameter names you need to ignore the first part of the declaration then you can refer the parameters as $0, $1, $2 and so on.
Example:-
1 2 3 4 |
var sayHello: (String, String) -> String sayHello = { $0 + $1 } print("W3Adda - Shorthand Parameter Names") print(sayHello("W3Adda - ", "Swift Tutorial")) |
Output:-
Swift Closures to Capture Values
In swift closure can hold the references of any variables or constants defined in its surrounding and later it can access or retrieve the value of those variables and constants based as per the requirement. Closure is allowed to modify variable or constant for which it holds the reference till program stops execution.
Example:-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
var num = 0 var plusOne = { num += 1 } var showNumber = { print(num) } print("W3Adda - Swift Closures to Capture Values.") showNumber() // 0 plusOne() // number is 1 showNumber() // 1 plusOne() // number is 2 plusOne() // number is 3 plusOne() // number is 4 showNumber() // 4 |
Output:-
Swift Closures Are Reference Types
In Swift closures are of reference types, which means if a closure is assigned to more than one variable or constant they will be pointing to the same closure.
Example:-
1 2 3 4 5 6 7 8 9 10 11 12 |
print("W3Adda - Swift Closures Are Reference Types") // a closure that double the given num and return it var doubleIt: (Int) -> (Int) = { num in return 2 * num } var d1 = doubleIt(5) // 10 print("Double of 5 is :\(d1)") // Pass reff. to closures var doubleItAgain = doubleIt var d2 = doubleItAgain(10) // 20 print("Double of 10 is :\(d2)") |
Output:-
Swift Escaping Closure
non escaping closure –
A closure that is passed to a function as a parameter is said to be non escaping closure it is being called before the return statement.
escaping closure –
A closure that is passed to a function as a parameter is said to be escaping closure it is being called after the return statement.In order to allow a closure to escape function body we need to add @escaping keyword before the parameter type to indicate that it escaping closure.
Example:-
1 2 3 4 5 6 7 8 9 10 11 12 |
print("W3Adda - Swift Escaping Closure") var closureArr:[()->()] = [] func functionWithEscapingClosure(myClosure:@escaping () -> Void) { print("function called") closureArr.append(myClosure) myClosure() return } functionWithEscapingClosure { print("closure called") } |
Output:-
Swift Autoclosures
In swift autoclosure allows to wrap closure expression passed as an argument to a function.In order to allow a closure to wrap closure statements we need to add @autoclosure keyword before the parameter type.
Example:-
1 2 3 4 5 6 |
func sampleFunction(sampleAutoClosure: @autoclosure ()->(), msg:String) { print(msg) sampleAutoClosure() } sampleFunction(sampleAutoClosure: (print("Hello from closure.")), msg:"Hello W3Adda!") |
Output:-