Question

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

Was it helpful?

Solution

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.

OTHER TIPS

This seems very confused. Or maybe you saw an example and removed too much code, so that it doesn't make sense anymore.

A "weak" object pointer doesn't keep a retain count on the object and becomes nil whenever the object is deallocated, which happens when the object loses its last retain count.

So whenever you see a "weak" object pointer, that pointer might be nil or change to nil soon. As a consequence, code like

[weakself method1];
[weakself method2];
[weakself method3];

should be avoided, because weakself might become nil after the first or second call, and calling only one or two methods could lead to wrong results. Instead you write

strongself = weakself;
[strongself method1];
[strongself method2];
[strongself method3];

strong self might be nil or not, but because it is a strong object pointer, it will hold a reference to the object (if it isn't nil), so all three methods will be called or none of them.

weakself->myproperty = @"Something";

is highly dangerous - it will crash if weakself is nil. So will

strongself = weakself;
strongself->myproperty = @"Something";

It is rarely correct to assign directly to instance variables, except inside the implementation of the class.

Minor addition: It's "former" and "latter", not "later". That's a case where a spelling mistake is very confusing, so you should try to avoid that.

1.used second one when you sure your code does not create any retain cycle.

2.now come to your problem

block are closures , they strongly refer to any object which it contain including self. so if self does not strongly refer block you can use your second syntax inside the block because retain cycle will not be generated. BUT if your self is also refer the same block strongly , then it will generate a retain cycle.

so you have to use your first syntax and you can later on strongify it inside the block according to your use.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top