Shall We Always Use [Unowned Self] Inside Closure in Swift

Shall we always use [unowned self] inside closure in Swift

No, there are definitely times where you would not want to use [unowned self]. Sometimes you want the closure to capture self in order to make sure that it is still around by the time the closure is called.

Example: Making an asynchronous network request

If you are making an asynchronous network request you do want the closure to retain self for when the request finishes. That object may have otherwise been deallocated but you still want to be able to handle the request finishing.

When to use unowned self or weak self

The only time where you really want to use [unowned self] or [weak self] is when you would create a strong reference cycle. A strong reference cycle is when there is a loop of ownership where objects end up owning each other (maybe through a third party) and therefore they will never be deallocated because they are both ensuring that each other stick around.

In the specific case of a closure, you just need to realize that any variable that is referenced inside of it, gets "owned" by the closure. As long as the closure is around, those objects are guaranteed to be around. The only way to stop that ownership, is to do the [unowned self] or [weak self]. So if a class owns a closure, and that closure captures a strong reference to that class, then you have a strong reference cycle between the closure and the class. This also includes if the class owns something that owns the closure.

Specifically in the example from the video

In the example on the slide, TempNotifier owns the closure through the onChange member variable. If they did not declare self as unowned, the closure would also own self creating a strong reference cycle.

Difference between unowned and weak

The difference between unowned and weak is that weak is declared as an Optional while unowned is not. By declaring it weak you get to handle the case that it might be nil inside the closure at some point. If you try to access an unowned variable that happens to be nil, it will crash the whole program. So only use unowned when you are positive that variable will always be around while the closure is around

Why would I ever use unowned self?

unowned has a marginal performance advantage over weak because the runtime doesn't have to keep track of the reference to turn it into nil when the object goes away.

In respect of retain cycles (well, strong reference cycles), neither weak nor unowned creates a strong reference (in pre ARC terms, neither increments the retain count) so there is no danger of a reference cycle, in fact, that is why you need to specify weak or unowned for self in closures.

Also, with unowned you can use the reference as a non optional, so you don't have to put any code in the closure to unwrap it.

I always use weak unless there is a really good performance reason not to.

NB in your code, I do not think either is necessary because the closure is not escaping i.e. The reference to it taken in the function call foo does not persist after the end of foo's scope.

When we should NOT use neither [weak self] nor [unowned self]?

You need to use [weak self] or [unowned self] if your closure can cause a Strong Reference Cycle.

This can occur if you assign the closure to a property of self and you refer to self or a property of self inside the closure itself. Closures are reference types, hence essentially the same rules apply to strong references as if you used normal classes.

As for your example, there is no need for [weak self] or [unowned self], since you don't assign the closure to a variable inside the class to which self refers to, so there won't be a strong reference cycle.

For more information, check out the Strong Reference Cycles for Closures part of the Swift programming language guide. Here is an example from the mentioned link of when a strong reference cycle can be caused by closures:

class HTMLElement {

let name: String
let text: String?

lazy var asHTML: () -> String = {
if let text = self.text {
return "<\(self.name)>\(text)</\(self.name)>"
} else {
return "<\(self.name) />"
}
}

init(name: String, text: String? = nil) {
self.name = name
self.text = text
}

deinit {
print("\(name) is being deinitialized")
}

}

Without [unowned self] in the closure of asHTML, a strong reference cycle will be caused by the closure assigned to asHTML. Changing the implementation of asHTML to the following solves this issue:

lazy var asHTML: () -> String = {
[unowned self] in
if let text = self.text {
return "<\(self.name)>\(text)</\(self.name)>"
} else {
return "<\(self.name) />"
}
}

Should I use [weak self] if I don't actually reference self in my completion block?

Capturing the variables, happens only when you use it internally, a closure will NEVER capture the variables by default (not like Java inner class which ALWAYS captures this), so, it you use a variable (including self) inside the closure, it is captured.

Also you can manually capture the variables using the [weak self], [weak your_variable_here], [unowned self], [unowned your_variable_here], [self] or [your_variable_here]

If the compiler tells you variable "self" is written to but never read from, it means that you didn't use self inside, so it is completely safe not to use [weak self], because self will NOT be captured, because it is not used.

weak self or unowned self is needed only when your closure captures self, and escapes the function it is passed to, especially if it is saved in a variable.

Refer to Closures in Apple's Official Swift Documentation

Why does [weak self] work but [unowned self] break in a Swift closure?

This sounds like a bug. {[unowned self] in self.twinkle()} should work identically to {[weak self] in self!.twinkle()}

Strong, weak and unowned self in closures explanation

It is not possible to say without looking at A.someFunctionA since it's unknown if completion is @escaping (e.g. if it's retained). For the rest of the answer I will assume that it is @escaping.

Swift needs to ensure runtime safety, and will keep any objects it might need in the future alive, in this case by making a strong reference to self (since self is the only variable used inside the closure).

In this scenario there is no reference cycle. This is because instanceA is not retained, so A => B, but B !=> A.

However, if instanceA was retained by B (let's say you create an instanceA: A property and set it) then you will have a retain cycle.

To get around this you can make variables within the closure either weak or unowned. They both do the same thing, but provide you with slightly different types. They both hold a weak reference, meaning that instanceA will not be increase the reference count of your B instance; if B is deallocated and there are no other reference, instanceA is also deallocated.

When using [weak self] self is optional, e.g. self: B?. However, [unowned self] is explicitly unwrapped, e.g. self: B!. This means that if the closure is called and self is nil your program will crash. This is why it's important to only use unowned when you know for certain that deallocating B will also deallocate A. There are a few scenarios where unowned is safe, e.g. the case when creating a closure and storing it on the same object that created it, but there are more nuances to this.

If unsure, use weak!



Related Topics



Leave a reply



Submit