Difference between Non-Escaping and Escaping Closures in Swift

Difference between Non-Escaping and Escaping Closures in Swift

In Swift, closures can be categorized as either escaping or non-escaping depending on their behaviour. In this blog post, we'll explore the difference between these two types of closures and how they can be used in your code.

What is a closure?

A closure is a self-contained block of functionality that can be passed around and used in your code. It can capture and store references to any constants and variables from the context in which it was defined, allowing it to access those values later. Closures in Swift are similar to blocks in Objective-C and lambdas in other programming languages.

Here is a simple example of a closure in Swift:

let numbers = [1, 2, 3, 4, 5]

let sortedNumbers = numbers.sorted { $0 < $1 }

print(sortedNumbers) // [1, 2, 3, 4, 5]

In this example, we're using the sorted method on an array of numbers. The sorted method takes a closure as its argument that defines how the numbers should be sorted. In this case, we're using a closure that compares two numbers and returns true if the first number is less than the second number.

Escaping closures

An escaping closure is a closure that is passed as a parameter to a function but is called after the function returns. This means that the closure is stored somewhere and can be called later, even after the function that originally received the closure has finished executing. Escaping closures are marked with the @escaping attribute.

Here is an example of a function that takes an escaping closure as a parameter:

func fetchData(completion: @escaping (Result<[String], Error>) -> Void) {
    // Perform some asynchronous operation to fetch data
    // When the operation completes, call the completion closure with the result
    let result: Result<[String], Error> = .success(["John", "Jane", "Jack"])
    completion(result)
}

In this example, the fetchData function takes a closure as a parameter that is used to handle the result of an asynchronous operation. The closure is marked with the @escaping attribute because it will be called after the fetchData function returns.

Non-escaping closures

A non-escaping closure is a closure that is passed as a parameter to a function and is called before the function returns. This means that the closure cannot be stored and called later outside of the function. Non-escaping closures do not need to be marked with any attributes.

Here is an example of a function that takes a non-escaping closure as a parameter:

func processNumbers(numbers: [Int], closure: (Int) -> Void) {
    for number in numbers {
        closure(number)
    }
}

In this example, the processNumbers function takes an array of numbers and a closure as parameters. The closure is used to process each number in the array and is called immediately inside the function.

Conclusion

In summary, closures are self-contained blocks of functionality that can be passed around and used in your code. They can be categorized as either escaping or non-escaping depending on their behavior. Escaping closures are passed as a parameter to a function but are called after the function returns, while non-escaping closures are called before the function returns. Understanding the difference between these two types of closures is important for writing efficient and safe code in Swift.

Let me know if you have any queries.