Could someone help me understand which approach is 'best' with regard to avoiding a block retain cycle..
__weak typeof(self) weakSelf = self;
weakSelf.myProperty = @"something";
vs
self->myProperty = @"something";
The later is being recommended by xCode 5.1 and the former is what seems to be historically recommended.
Thanks
The only time Apple really talks about self->_ivar
syntax is when they're observing out that a reference to some instance variable, _ivar
, alone, is really equivalent to self->_ivar
, and thus referring to _ivar
within a block will implicitly retain self
. But they're not really recommending you use self->_ivar
, just pointing out the issue associated with using instance variables within blocks, that they entail implicit references to self
.
You said:
A 'Semantic Issue' warning generated by Xcode. The issue is described as "Block implicitly retains self". The 'fix-it' pop generated by Xcode suggests 'Insert self->'
I can only guess that the suggestion by Xcode is to ensure that implicit references to self
are replaced with explicit references, and thus, when you employ the weakSelf
pattern, you'll be able to see each reference to self
that needs replacing. Clearly, it would be hard for Xcode to know the name of your __weak
rendition of self
, so it's hard for it to suggest that, but their proposed edit does help avoid missing some implicit reference to self
.
By the way, once you convert those ivar references, e.g. _ivar
, with self->_ivar
, it will be tempting to then simply go through the code in the block, replacing the references to self
with your new weakSelf
variable. But be careful: The construct weakSelf->_ivar
is problematic because if weakSelf
is nil
, that will generate a EXC_BAD_ACCESS
at runtime. If this ivar is simply backing some property, then use the property (e.g. weakSelf.property
). Property accessor methods correctly handle nil
pointers (doing nothing), but dereferencing an ivar of a nil
pointer will generate the EXC_BAD_ACCESS
.
Ideally in that scenario, just use the property accessor method instead and you're done. But, if there is no property associated with this _ivar
, then you have to employ the pattern joking referred to as the "weakSelf
/strongSelf
dance". So, let's assume you had code that looked like:
someBlockVariable = ^{
// do something
// now try to set an ivar
_ivar = ...;
};
Doing that _ivar
to self->_ivar
change that Xcode suggests, and then substituting weakSelf
, you'd end up with:
typeof(self) __weak weakSelf = self;
someBlockVariable = ^{
// do something
// now try to set an ivar
weakSelf->_ivar = ...;
};
But that's bad (for the reasons I describe above). In fact, the compiler will even warn you that you cannot dereference a weak pointer. So what you'd want to do is:
typeof(self) __weak weakSelf = self;
someBlockVariable = ^{
// do something
// now try to set an ivar
typeof(self) strongSelf = weakSelf;
if (strongSelf) {
strongSelf->_ivar = ...;
}
};
And don't worry about the reference to typeof(self)
in the block, as that will not retain self
.