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.
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.
Use __unsafe_unretained typeof(self) weakSelf = self;
In addition to @NikolaiRuhe's response, in your example when declaring the properties
BOOL *iis = isItSaving;
id myself = self;
implies strong
references, so use __weak
self to prevent the retain cycle. Then you might wonder why you need to declare a __strong
reference to weak self within the block, and that's to make sure it doesn't get released during the life of the block, otherwise weakSelf->isItSaving
would break if self
was released.