Why Specify [Unowned Self] in Blocks Where You Depend on Self Being There

Why specify [unowned self] in blocks where you depend on self being there?

"The Language Guide claims you should use unowned if the closure and containing object reference each other and will be destroyed at the same time. Presumably that's to avoid the cost of safely nil'ing out a weak reference in an object that's about to dealloc anyway."

http://www.russbishop.net/swift-capture-lists

So [unowned self] makes self an an implicitly unwrapped optional, for the convenience of not unwrapping it yourself, at the risk of a crash if of course it is actually nil.

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.

Should l I use [unowned self] for Realm.write()?

If you have a look at the write method declaration, you will see, that the closure is non escaping. So, you don't need to use neither weak nor unowned. It will not lead to retain cycle.

public func write(_ block: (() throws -> Void)) throws {
beginWrite()
do {
try block()
} catch let error {
if isInWriteTransaction { cancelWrite() }
throw error
}
if isInWriteTransaction { try commitWrite() }
}

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

What is this `[unowned self] in` Swift code doing?

What is the navigationCallback being assigned to?

The stuff in curly braces constitutes an anonymous function. It's like a block in Objective-C.

What is [unowned self]?

The stuff in square brackets preceding in in the anonymous function's capture list. It prevents a retain cycle by bringing self into the anonymous function unretained. unowned is like an assign property policy in Objective-C (non-ARC weak). In Objective-C you'd typically do the weak-strong dance in order to do something similar.

Capturing self weak or unowned on asynchronous network requests

If you capture self without weak or unowned keywords, your view controller will be retained by the closure and will not deallocate before the closure dies. The difference between weak and unowned is that weak is an Optional and requires conditional binding as a safety check. On the other hand, unowned is not as fail-safe. It assumes that your view controller is still alive and it will crash if it is not. For more information see this answer.

Using method with self inside blocks

It is not safe to do this, even if many people a doing it like this.

You should use the "weakSelf" pattern with blocks when it is justified.
In your example the "weakSelf" pattern is not justified, because self don't have any strong reference to your block. You can use like this :

[_dataProvider doA:^(NSError *error) {
// here you can use self, because you don't have any strong reference to your block

[weakSelf handleError:error];
}];

Use "weakSelf" pattern if you have a strong reference to your block ( with a property or an instance variable for example) and your are capturing self inside the block, example :

 @property(strong) void(^)(void) completionBlock;
....

__weak typeof(self) weakSelf = self;

self.completionBlock = ^{
// Don't use "self" here, it will be captured by the block and a retain cycle will be created
// But if we use "weakSelf" here many times, it risques that it will be nil at the end of the block
// You should create an othere strong reference to the "weakSelf"
__strong typeof(self) strongSelf = weakSelf;
// here you use strongSelf ( and not "weakSelf" and especially not "self")
};


Related Topics



Leave a reply



Submit