Search Your Question

What is capture and capture list in closure?

Ans :

According to apple document :

Closures are self-contained blocks of functionality that can be passed around and used in your code. Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages. 

Closures can capture and store references to any constants and variables from the context in which they are defined. This is known as closing over those constants and variables. Swift handles all of the memory management of capturing for you.

Closure is reference type

Capturelist is used to stop memory leakage.

Code for Example of memory leakage :


class Increment {
    var number = 0

     deinit {
        print(#function)
    }
    
    lazy var incrementNumber: (Int) -> () = { value in
        self.number += value
        print(self.number)
    }
}

 do {
  let increment = Increment()

  increment.incrementNumber(3
 }


This will cause memory leak, the closure refers back to the object itself, it refers to self in order to increment the number, and that will create a reference cycle:

We have an object and the object has a stored property that refers to a closure.
That closure refers back to self (means Increment instance)

In above example, deinit should be called. But it never due to retain cycle created.

To Stop memory leakage we use capture list :

1. [unowned self]
2. [weak self]
3. [strong self] - Default

1.

lazy var incrementNumber: (Int) -> () = { [unowned self] value in
        self.number += value
        print(self.number)
    }

If I use [unowned self] there here less chance to crash. But if we use
let increment = Increment().incrementNumber(3)
then there will be more chance to be crashed. We can not immediately call incrementNumber method after object instantiated. Because when the stored property has returned, the object (increment instance) can be deallocated, nothing else is referring to it.

2.

 let’s change [unowned self] to [weak self], that means that everywhere that self is accessed, we treat it as a weak property. While using weak, we should use optional self? to access property.

When the stored property has returned, if the object be deallocated, mean self is nil, then the number will not be incremented. This code will make it easy to handle if self is nil

So when no clue to what to use, we should use [weak self] as capture list.





No comments:

Post a Comment