[英]If a strong property has a block that refers to self, is that a retain cycle?
例如:
[self.contentWrapperView addGestureRecognizer:
[UITapGestureRecognizer recognizerWithHandler:^(UIGestureRecognizer *sender,
UIGestureRecognizerState state,
CGPoint location) {
if (self.customEditing) {
[self setEditingMode:NO Animated:YES];
}
}]];
其中contentWrapperView
是self
的强属性,并且假定contentWrapperView
具有对识别器块的强引用。 在块中使用self
是否会导致保留周期? 这是我不太了解的唯一部分。
是的,这将导致保留周期。
万一您关心的解决方法是
__weak id weakSelf = self;
[self.contentWrapperView addGestureRecognizer:[UITapGestureRecognizer recognizerWithHandler:^(UIGestureRecognizer *sender, UIGestureRecognizerState state, CGPoint location) {
if ([weakSelf customEditing]) {
[weakSelf setEditingMode:NO Animated:YES];
}
}]];
考虑一下保留周期的实际含义:通过拥有的对象对自己的保留。
用Cocoa和Cocoa-Touch的术语来说,这意味着您强烈拥有的任何变量都不能反过来强烈拥有您 。 这通常是通过声明一个属性需要weak
, unsafe_unretained
,未unsafe_unretained
或assign
父属性来解决的。 这会因块而变得复杂,而块通常像闭包一样捕获对它们中每个变量的const或保留引用(显然, __block
限定符会使其更加复杂)。
与其从块的角度看待这个问题,我将尝试将其抽象为带有两个类的示例,这对于使用OO lang的人来说通常更容易实现:
假设我有MyImportantObject
类,该类需要与另一个MyWorkerClass
类做一些工作。 通常,我们通常需要对MyWorkerClass
的强引用,因为也许我们希望它能坚持下去,以便我们以后可以做更多的工作,或者一遍又一遍地调用相同的worker方法:
@interface MyImportantObject : NSObject
@property (nonatomic, strong) MyWorkerClass *workerObj;
@end
反过来,我们的工作人员需要稳定引用其需要工作的所有MyImportantObject
的属性(否则它将无法工作 !)。 因此,引用self
块会执行什么操作,而不是对每个变量采用const或保留引用,而是对其父对象保留引用!
@interface MyWorkerClass : NSObject
@property (nonatomic, strong) MyImportantObject *workerObj;
@end
这意味着如果您尝试使用MyImportantObject
的辅助对象,它们将相互保留,并且不会被正确释放! 巨大的不。
通过将self
转移到__weak
(或MRC下的__block
)指针中,我们得到的引用看起来像这样:
@interface MyWorkerClass : NSObject
@property (nonatomic, weak) MyImportantObject *workerObj;
@end
不再有保留周期,每个人都高兴,当父母沿着恐龙的路走时,每个人都被适当地释放。
但是还有一个难题:我们如何处理weak
引用? 毕竟,我们说好ol编译恶有恶报和猛拉self
从你下了一个快速-release
。 由于归零弱指针,您现在在块中有一个运行amok的nil指针。 这可能导致它实际上什么也没做,而您坐在那里挠头想知道为什么。 这导致了我称之为弱劲舞的发明。
J_mcnally的示例缺少舞蹈中的关键一步,即自我指针的“重新增强”。 但是,在我们为避免保留周期而费尽心思之后,为什么还要这样做呢? 这是因为我们的X的强副本没有被块保留,而是被块的scope保留了。 用英语来说,这意味着我们强大的self
只会在到达块的末尾时才释放,从而不仅保证了安全的内存循环,而且也不会从我们下面释放它。 正确的修复如下所示:
__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.
}]];
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.