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

后端 未结 3 961
情书的邮戳
情书的邮戳 2021-02-03 11:00

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

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

相关标签:
3条回答
  • 2021-02-03 11:17

    Use __unsafe_unretained typeof(self) weakSelf = self;

    0 讨论(0)
  • 2021-02-03 11:29

    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.

    0 讨论(0)
  • 2021-02-03 11:36

    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.

    0 讨论(0)
提交回复
热议问题