Difference between escaping and non escaping closures

In this post we are going to learn, difference between escaping closures and non-escaping closures. Closures are self contained block of functionality that can be pass around and used in your code. Learn about closures in swift from given below link

https://iostutorialjunction.com/2018/04/how-to-write-closures-in-swift-beginner-tutorial.html

Closures types

There are two type of closures

  • Escaping closures
  • Non-escaping closures

What are Non-Escaping closures?

A closure is non-escaping closure by default in swift. With non-escaping means that a closure will not live or remain in memory once the function that calls this closure finish execution. It means closure needs to be executed before its calling function finish execution.

Example of Non-Escaping closure

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        addTwoNumbers()
    }
    
    func addTwoNumbers() {
            print("Step 1")
        performSumFor(10, andSecodNumber: 20) { (result) in
            print("Result == \(result)")
        }
        print("Last Step")
    }
    
    func performSumFor(_ num1: Int, andSecodNumber num2:Int, completionHandler: @escaping (_ resilt:Int) -> Void) {
        print("Step 2")
        let result = num1 + num2
        print("Step 3")
        completionHandler(result)
    }
}

In above example you, we have a function named, performSumFor , that accepts three parameters and one of them is a closure. In our second function, addTwoNumbers, we are calling performSumFor. Also we have listed steps of execution. If you run this example, output for execution will be like this

  • Step 1
  • Step 2
  • Step 3
  • Result == 30
  • Last Step

Here yo can see clearly, that before ‘Last Step’ gets printed out, our closure finished execution and thus de-allocated from memory and in other words it did not escaped the function from which it gets called.

What are Escaping closures?

Escaping closure are exact opposite of non-escaping closures. It means escaping closures will remain in memory after the function from which they gets called finish execution. You have seen escaping closures in case of API calls where code is running asynchronously and execution time is unknown. Let us look at the example, we will use same example as used above but we will call closure asynchronously.

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        addTwoNumbers()
    }
    
    func addTwoNumbers() {
            print("Step 1")
        performSumFor(10, andSecodNumber: 20) { [weak self] (result) in
            guard let _ = self else {return}
            print("Result == \(result)")
        }
        print("Last Step")

    }
    
    
    func performSumFor(_ num1: Int, andSecodNumber num2:Int, completionHandler: @escaping (_ resilt:Int) -> Void) {
        print("Step 2")
        let result = num1 + num2
        
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) {
            print("Step 3")
            completionHandler(result)
        }   
    }
}

Inn above code, we only add comletionHandler execution line inside async queue. OUtput of above code will be

  • Step 1
  • Step 2
  • Last Step
  • Step 3
  • Result == 30

So here we saw clearly, that our closure gets executed or called after the addTwoNumbers functions finished its execution. So this means, the closure will remain in memory and thus we have to add [Weak self] in closure body.

Where to go from here

In this tutorial, you learned difference between escaping and non-escaping closures in swift with example of each case.