在这个区块强烈捕捉“自我”可能会导致一个保留周期
我有块要求。 但编译器发出警告
“在这个区块强烈地捕捉”自我“可能会导致一个保留周期”
__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
指针是不允许的,因为由竞争条件引起的可能的空值,首先将其分配给strong
variables
因此,您可以通过使用weakSelf
模式来解决此问题,但也可以在块中创build一个本地strong
variables,并使用该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