在这个区块强烈捕捉“自我”可能会导致一个保留周期

我有块要求。 但编译器发出警告

“在这个区块强烈地捕捉”自我“可能会导致一个保留周期”

__weak typeof(self) weakSelf = self; [generalInstaImage setImageWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:data[@"images"][@"low_resolution"][@"url"]]] placeholderImage:[UIImage imageNamed:@"Default"] success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) { NSLog(@"success"); [generalInstaImage setImage: image]; [weakSelf saveImage:generalInstaImage.image withName:data[@"id"]]; } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) { NSLog(@"fail"); }]; 

我尝试写例如weakSelf.generalInstaImage示例,但编译器生成一个错误,不编译。

考虑这个警告:

在这个区块强烈捕捉self可能会导致一个保留周期

当您收到上述警告,您应该检查您的块为:

  • 明确提及self ; 要么
  • 通过引用任何实例variables引起的任何隐式引用。

让我们想象一下,我们有一些简单的类属性是一个块(这将经历与您的问题相同的“保留周期”警告,但会让我的示例更简单一些):

 @property (nonatomic, copy) void (^block)(void); 

让我们假设我们有一些其他的类属性,我们想在我们的块中使用:

 @property (nonatomic, strong) NSString *someString; 

如果你在块中引用self (在我的例子中,在访问这个属性的过程中),你显然会收到有关保留周期风险的警告:

 self.block = ^{ NSLog(@"%@", self.someString); }; 

这可以通过你所build议的模式来解决,即:

 __weak typeof(self) weakSelf = self; self.block = ^{ NSLog(@"%@", weakSelf.someString); }; 

不太明显的是,如果引用块中的类的实例variables,则还会收到“保留周期”警告,例如:

 self.block = ^{ NSLog(@"%@", _someString); }; 

这是因为_someString实例variables携带对self的隐式引用,实际上等价于:

 self.block = ^{ NSLog(@"%@", self->_someString); }; 

你也可能倾向于尝试在这里采用虚弱的自我模式,但是你不能。 如果您尝试weakSelf->_someString语法模式,编译器会警告您:

取消引用__weak指针是不允许的,因为由竞争条件引起的可能的空值,首先将其分配给strongvariables

因此,您可以通过使用weakSelf模式来解决此问题,但也可以在块中创build一个本地strongvariables,并使用该variables来取消引用实例variables:

 __weak typeof(self) weakSelf = self; self.block = ^{ __strong typeof(self) strongSelf = weakSelf; if (strongSelf) { NSLog(@"%@", strongSelf->_someString); // or better, just use the property // // NSLog(@"%@", strongSelf.someString); } }; 

strongSelf ,在块内创build一个本地strong引用strongSelf也具有其他优点,即如果完成块在asynchronous线程上asynchronous运行,则不必担心self被释放,块正在执行,导致意想不到的后果。

这个weakSelf / strongSelf模式在处理块属性时非常有用,并且希望防止保留周期(也称为强引用周期),但同时确保在完成块的执行过程中不能释放self

仅供参考,Apple在“ 转换到ARC版本说明 ”的“ 使用寿命限定符避免强参考周期”部分进一步讨论了“非平凡循环”讨论了这种模式


你报告你在你的例子中引用weakSelf.generalInstaImage时候收到了一些“错误”。 这是解决这个“保留周期”警告的正确方法,所以如果您收到警告,您应该与我们分享,并告诉我们您是如何申报的。

使用__unsafe_unretained typeof(self) weakSelf = self