iOS interview questions (4)

Closures & Strong Reference Cycles for Closures
It is very hot topic for interview as it provides questions from beginner level to expert level, and most of the engineer got confused in it during discussion, even when you try to use it in your…

Chapter 4: Closures & Strong Reference Cycles for Closures

It is very hot topic for interview as it provides questions from beginner level to expert level, and most of the engineer got confused in it during discussion, even when you try to use it in your real life project, you may face some situation where you got confuse what to use and what not to!

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

Closure Expression Syntax

Escaping Closures

A closure is said to escape a function when the closure is passed as an argument to the function, but is called after the function returns. When you declare a function that takes a closure as one of its parameters, you can write @escaping before the parameter’s type to indicate that the closure is allowed to escape.

reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } ) //(Line 1)

reversedNames = names.sorted(by: { $0 > $1 } ) //(Line 2)

Both lines are doing same thing, Line 1 is called Implicit Returns from Single-Expression Closures & Line 2 is called Shorthand Argument Names which can be used to refer to the values of the closure’s arguments by the names $0, $1, $2, and so on.

Strong Reference Cycles for Closures

This strong reference cycle occurs because closures, like classes, are reference types.

Case : if you assign a closure to a property of a class instance, and the body of that closure captures the instance.

Description: This capture might occur because the closure’s body accesses a property of the instance, such as self.someProperty, or because the closure calls a method on the instance, such as self.someMethod(). In either case, these accesses cause the closure to “capture” self, creating a strong reference cycle.

Solution: Weak or Unowned References, The appropriate choice of weak or unowned depends on the relationships between the different parts of your code.

The Question: Unowned or Weak?

Which one of the two reference types should you use?

“Use a weak reference whenever it is valid for that reference to become nil at some point during its lifetime. Conversely, use an unowned reference when you know that the reference will never be nil once it has been set during initialization.”

“Define a capture in a closure as an unowned reference when the closure and the instance it captures will always refer to each other, and will always be deallocated at the same time.”

There are two possible scenarios:

  • The closure has the same lifetime of the captured object, so the closure will be reachable only until the object will be reachable. The external object and the closure have the same lifetime (e.g. simple back-references between and object and its parent). In this case, you should declare the reference as unowned.
    A common example is the [unowned self] used in many examples of small closures that do something in the context of their parent and that not being referenced or passed anywhere else do not outlive their parents.
  • The closure lifetime is independent from the one of the object being captured, the closure could still be referenced when the object is not reachable anymore. In this case you should declare the reference as weak and verify it’s not nil before using it (don’t force unwrap).
    A common example of this is the [weak delegate = self.delegate!] you can see in some examples of closure referencing a completely unrelated (lifetime-wise) delegate object.

lazy var

A lazy stored property is a property whose initial value is not calculated until the first time it is used. You indicate a lazy stored property by writing the lazy modifier before its declaration.

defer keyword

What defer does is not obvious at first. Defer will wait to execute a block of code until the current scope (loop, method, etc) is exiting. And it will execute that code whether the scope is exiting cleanly, from a guard, or while an error is being thrown.

Here’s the most basic of examples. The defer block exists before the main body of the code, but it’s not called until afterwards.

This can be useful if, for example, there are resources you need to ensure are cleaned up before leaving the current scope.

Conclusion

Does using defensively only weak references make sense? No, from both the point of view of performance and code clarity.

Using the right type of capture modifier makes explicit some lifetime characteristics of our code and makes it harder to reach wrong conclusions about how the code behaves when someone else, or future you, will read what you wrote.

Hope you are loving it!