In Objective-C, what does it mean to assign a weak
to a strong
within a block? What's happening behind the scene?
e.g.
__weak __typeof(self) wself = self;
void (^cmd)() = ^(){
__strong __typeof(self) sself = wself;
if (!sself) return;
...
};
strong is the default. An object remains “alive” as long as there is a strong pointer to it. weak specifies a reference that does not keep the referenced object alive. A weak reference is set to nil when there are no strong references to the object.
Pointers that are not retained are often referred to as “weak” in Objective-C documentation that predates the garbage collector. These are references that are allowed to persist beyond the lifetime of the object. Unfortunately, there is no automatic way of telling whether they are still valid.
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.
For example, a strong reference keeps a firm hold on instances and doesn't allow deallocation by ARC. Similarly, a weak reference cannot protect the instances from being deallocated by ARC. Before you learn about strong and weak reference, make sure to understand how classes and objects work in Swift.
The intent here is two-fold:
First, is the use of:
__weak __typeof(self) wself = self;
This ensures that the cmd
block does not maintain a strong reference to self
. This ensures that, if cmd
was an instance variable of the class, that you don't end up with a strong reference cycle. If you don't use this wself
pattern, the class that has cmd
as an instance variable would never be released and you'd leak the object that has cmd
as an instance variable.
For more information, see the Avoid Strong Reference Cycles when Capturing self section of the Programming with Objective-C: Working With Blocks document.
Second, the use of the following within the block:
__strong __typeof(self) sself = wself;
if (!sself) return;
This ensures that, if the block starts execution, if wself
was already deallocated, the block would quit. But if wself
has not yet been deallocated, by assigning sself
, you're making sure that the object will be retained during the execution of the block.
Also, if you reference any ivars in the block, be aware that you want to dereference them (because otherwise there is an implicit reference to self
in the block, potentially leading to that strong reference cycle). But you cannot dereference ivars using a weak pointer (e.g. wself->someIvar
is not permitted), but you can with this local strong pointer (e.g. sself->someIvar
is ok). Generally you shouldn't be dereferencing ivars anyway, but rather use properties, but nonetheless it's another reason to use a local strong reference to self
.
Often, you'll see this construct in conjunction with a class property (or an ivar):
@property (nonatomic, copy) void (^commandBlock)(void);
And, as a matter of convention, you'll generally see more descriptive variable names, weakSelf
and strongSelf
, thus:
__weak __typeof(self) weakSelf = self;
self.commandBlock = ^(){
__strong __typeof(self) strongSelf = weakSelf;
if (!strongSelf) return;
...
};
This weakSelf
/strongSelf
pattern is very common when you have your own block properties to your class and you want to (a) prevent strong reference cycles (aka retain cycles); but (b) want to ensure that the object in question cannot be deallocated in the middle of the execution of the block.
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