SpaceDog SpaceDog - 3 months ago 22
Objective-C Question

Avoiding the "capturing self strongly in this block is likely to lead to a retain cycle" message

every time I have to use a global var or property inside a block like this:

self.save = ^(){
if (isItSaving == NO) {
[self saveMyFile];
}
};


I have to rewrite this like

BOOL *iis = isItSaving;
id myself = self;

self.save = ^(){
if (iis == NO) {
[myself saveMyFile];
}
};


or Xcode will complain "capturing self strongly in this block is likely to lead to a retain cycle...

It complains even about BOOL variables?

Redeclaring everything before a block appears to be a lame solution.

Is this the correctly way? Is there an elegant way?

This stuff is ugly. I am using ARC.

Answer

The problem only occurs when referencing self from within the block, explicitly or implicitly. There's no warning emitted when accessing global variables.

In your case you probably accessed a (boolean) ivar. Accessing the ivar implicitly uses self, that's why the compiler is warning you (correctly) about a retain cycle.

The common way to fix the retain cycle is:

typeof(self) __weak weakSelf = self;

self.save = ^() {
    typeof(weakSelf) __strong strongSelf = weakSelf;
    if (strongSelf != nil && ! strongSelf->isItSaving) {
        [strongSelf saveMyFile];
    }
};

... and, yes, that's a bit of an ugly part of blocks.