根据实际情况考虑保留周期:您拥有的对象保留您自己。
用 Cocoa 和 Cocoa-Touch 的术语来说,这意味着你强烈拥有的任何变量都不能反过来强烈拥有你。这通常通过声明需要拥有其父级的属性来解决weak
,unsafe_unretained
或者assign
. 这会因块而变得复杂,这些块通常像闭包一样捕获对其中每个变量的 const 或保留引用(显然,__block
限定符会进一步复杂化)。
我不会从块的角度来看这个,而是尝试将它抽象为一个包含两个类的示例,这对于那些使用 OO 语言的人来说通常更容易理解:
假设我有课MyImportantObject
,需要与另一个课做一些工作MyWorkerClass
。我们通常需要对 的强引用MyWorkerClass
,因为也许我们希望它保留下来,以便我们以后可以做更多的工作,或者继续一遍又一遍地调用相同的工作方法:
@interface MyImportantObject : NSObject
@property (nonatomic, strong) MyWorkerClass *workerObj;
@end
反过来,我们的 worker 需要一个稳定的引用来引用MyImportantObject
它需要工作的所有属性(否则它不能工作!)。那么该引用self
的作用是什么,而不是对每个变量采用 const 或保留引用,而是对其父级采用保留引用!
@interface MyWorkerClass : NSObject
@property (nonatomic, strong) MyImportantObject *workerObj;
@end
这意味着如果您尝试使用MyImportantObject
'worker 对象,它们会相互保留,并且都不会被正确释放!巨大的不,不。
通过分流self
到一个__weak
(或__block
在 MRC 下)指针,我们得到一个如下所示的引用:
@interface MyWorkerClass : NSObject
@property (nonatomic, weak) MyImportantObject *workerObj;
@end
没有更多的保留周期,每个人都很开心,当父母走恐龙的道路时,每个人都会被正确地释放。
但还有一个难题:我们如何处理weak
参考?毕竟,假设好的 ol' 编译器出现并self
快速从你下面拉出来-release
。由于该归零弱指针,您现在有一个 nil 指针在您的块中运行异常。这可能导致它实际上什么都不做,而您坐在那里挠头想知道为什么。这导致了我将称之为弱-强舞蹈的发明。
J_mcnally 的示例缺少关键的一步,即自我指针的“重新强化”。但是,在我们竭尽全力避免保留循环之后,为什么还要这样做呢?这是因为我们的 X 的强副本没有被块保留,它被块的范围保留。用英语来说,这意味着我们的 strongself
只会在到达块末尾时释放,因此不仅保证了安全的内存周期,而且它不会从我们下面被释放。正确的修复如下所示:
__weak id weakSelf = self;
[self.contentWrapperView addGestureRecognizer:[UITapGestureRecognizer recognizerWithHandler:^(UIGestureRecognizer *sender, UIGestureRecognizerState state, CGPoint location) {
id strongSelf = weakSelf;
if ([strongSelf customEditing]) {
[strongSelf setEditingMode:NO Animated:YES];
}
//Do some other stuff before strongSelf passes out of scope.
}]];