Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 597
Duck Avatar asked Apr 17 '13 18:04

Duck


2 Answers

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.

like image 121
Nikolai Ruhe Avatar answered Oct 06 '22 01:10

Nikolai Ruhe


Use __unsafe_unretained typeof(self) weakSelf = self;

like image 26
SandeepM Avatar answered Oct 06 '22 00:10

SandeepM