Discover practical insights and hands-on examples for leveraging code blocks with impact.
What is Closure?
Group code that executes together, without creating a named function.
Closures are self-contained blocks of functionality that can be passed around and used in your code.
In simpler words,
Closure Expression
Anonymous function or block of code
{ (parameters) -> return type in
}
Benefits
Good example — sorted function
let names = ["Lorem", "ipsum", "dolor", "sit", "amet"]
func reverseNames(_ s1: String, _ s2: String) -> Bool {
return s1 > s2
}
Capturing Values
Closure can capture constants and variables from the context.
The simplest form of closure that captures values is a nested function. A Nested Function can capture values from the outer function and inside the function.
func addCount(forCount amount: Int) -> () -> Int {
var total = 0
func counter() -> Int {
total += amount
return total
}
return counter
}
// Counter doesn't have any paramter but returns Int value
// Capturing by reference
// Swift handles memory management involved for Capturing Values
let countByTen = addCount(forCount: 10)
print(countByTen()) //prints 10
Functions and Closure are Reference Types
let addCountbyTen = countByTen
print(addCountbyTen()) // prints 20
print(countByTen()) // prints 30
Trailing Closures
Can be called Special Syntax. Rather than passing in your closure as the parameter, you can pass after the function inside the braces()
If you need to pass a closure expression to a function as the function’s final argument and the closure expression is long, it can be useful to write it as a trailing closure instead.
Way to make your code look cleaner and more readable when using functions or methods that take closures as arguments.
Making your code more natural
Good example — Sorted Example: names.sorted { $0 > $1}
func makeAddOfTwoNumbers(digits: (Int, Int), onCompletion: (Int) -> Void) {
let sum = digits.0 + digits.1
onCompletion(sum)
}
makeAddOfTwoNumbers(digits: (7,9)) { sum in
print(sum)
}
Escaping Closures @escaping attribute Preserved to be executed later.
Life Cycle
Benefits:
let url = URL(string: "https://swiftpublished.com/")!
let data = try? Data(contentsOf: url)
// Function to call the escaping closure
func loadData(completion: @escaping (_ data: Data?) -> Void) {
DispatchQueue.global().async {
let data = try? Data(contentsOf: url)
DispatchQueue.main.async {
completion(data)
}
}
}
loadData { data in
guard data != nil else {
// Handle error
return
}
}
Non-Escaping Closures
They are Default Closures. Preserved to be executed immediately.
Lifecycle
Benefits:
func getSum(of array: [Int], completion: (Int) -> Void) {
var sum: Int = 0
for i in 0..<array.count {
sum += i
}
print(sum)
completion(sum)
}
getSum(of: [1,2,3,4,5]) { sum in
print("SumArray \(sum)")
}
Autoclosures Automatically created to wrap a piece of code. Delay the execution of closure until it is actually needed.
Uses:
assert(::file:line:) precondition(::file:line:) assertionFailure(::file:line:)
func logIfTrue(_ condition: @autoclosure() -> Bool) {
if condition() {
print("True")
} else {
print("False")
}
}
logIfTrue("Saba" > "pathy")
Autoclosure with @escaping attribute
func delayedPrint(delay: Double, closure: @escaping @autoclosure () -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
closure()
}
}
print("Start 2")
delayedPrint(delay: 5, closure: print("Hellow Saba"))
Did you Know?
func execute(closure: SimpleClosure) {
print("Executing Closure")
closure()
}
let helloClosure: SimpleClosure = {
print("Hello World")
}
execute(closure: helloClosure)
Please find the complete playground
This is a free third party commenting service we are using for you, which needs you to sign in to post a comment, but the good bit is you can stay anonymous while commenting.