Why is it necessary to have a strong reference to a weak reference inside a block?
I understand that having a weak reference inside the block will avoid retain cycles. But why must there be a strong reference to the weak one again?
Background:
As described by Mason this is best practice.
I know the proper way to refer to self inside a block is to create a weak reference outside the block, and then a strong reference to that weak reference inside the block[...]
Example:
__weak typeof(self) weakSelf = self;
void (^someBlock)(id) = ^(id data){
typeof(self) strongSelf = weakSelf;
// code using strongSelf
});
A weak reference is just a pointer to an object that doesn't protect the object from being deallocated by ARC. While strong references increase the retain count of an object by 1, weak references do not. In addition, weak references zero out the pointer to your object when it successfully deallocates.
The garbage collector cannot collect an object in use by an application while the application's code can reach that object. The application is said to have a strong reference to the object. A weak reference permits the garbage collector to collect the object while still allowing the application to access the object.
For many of us, it's best practice to always use weak combined with self inside closures to avoid retain cycles. However, this is only needed if self also retains the closure. By adding weak by default you probably end up working with optionals in a lot of cases while it's actually not needed.
There are two types of object reference: Strong references, which keep an object “alive” in memory. Weak references, which have no effect on the lifetime of a referenced object.
Imagine that the last remaining strong reference to self is held on a different thread to the one that your block runs on.
Now this happens:
__weak typeof(self) weakSelf = self;
void (^someBlock)(id) = ^(id data){
if (weakSelf != nil) {
// last remaining strong reference released by another thread.
// weakSelf is now set to nil.
[myArray addObject:weakSelf];
}
});
This will crash with an NSInvalidArgument exception for adding nil to an array.
Making the reference strong before use removes the potential race condition and ensures that the pointer will always point to the same object.
If you are 100% certain that an object will only ever be referenced by one thread, it isn't strictly necessary to do this. But it's bad practice to make that assumption.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With