UIGestureRecognizer导致循环保留?

18

我在想,如果你在手势识别器的initWithTarget:action:方法中将目标分配为self,那么会导致循环保留吗?因为self将保留self.gestureRecognizers中的识别器,而且可能手势识别器也会在initWithTarget:action中保留自己。

以下是否为其解决方案?

__weak VRDrawer* weakSelf = self;
UIGestureRecognizer* tapRec = [[UITapGestureRecognizer alloc] initWithTarget:weakSelf
                                                                      action:@selector(handleTap:)];

3
你认为手势识别器会保留目标吗?在分配手势识别器的代码前后打印[self retainCount]应该很简单,以检查它是否发生了变化。 - Geoff Hackworth
5
@GeoffHackworth: http://www.whentouseretaincount.com - vikingosegundo
1
@GeoffHackworth 我不知道它是否保留目标,但是既然文档没有提到,我们应该怀疑一下。 - Meda
当你有疑问时,就进行测试。使用retainCount并观察结果!你会得到答案,然后移除对retainCount的调用。这再简单不过了。 - Geoff Hackworth
2
@GeoffHackworth 你知道 retainCount 的输出是不可靠的吗?你也知道在 ARC 下不能使用它,对吧?而且,如果你想知道,__weak 表示我正在使用 ARC。 - Meda
2
@GeoffHackworth,相信我:网站是正确的 - 即使是用于打印调试信息,也不要使用retainCount - vikingosegundo
2个回答

22

我完全理解在缺乏文档支持时确认某事可能感到不安。需要注意的重要事项是,通过十多年的惯例,目标-操作关系从未是 strong (强引用)。有相关文档。请注意其中的一部分内容:

控件对象不会(也不应该)保留它们的目标。

"保留…" 在 MRC 中意味着 "拥有一个强引用…"

鉴于这是此类交互的文档约定,请确信如果 UIGestureRecognizer 的目标-操作实现确实保留对象,那么这种异常情况足够奇怪,以至于它会出现在其文档中。


P.S. 您不必担心与控件在内存管理环境下保留目标的注释。"内存管理" 指的是 Cocoa 中(现已弃用的)垃圾收集。MRC 或 ARC 都不是内存管理。


与此同时,在其他不太远的世界中,对于NSNotificationCenter来说则完全相反:“您必须在由addObserverForName: object: queue:usingBlock:指定的任何对象被解除分配之前调用removeObserver:或removeObserver:name:object:”这也解释了为什么我的dealloc方法中删除操作从未奏效。 - Dan Rosenstark

4
UIGestureRecognizer* tapRec = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];

这不会保留自身。文档中也应该注明
你需要向视图添加一个识别器。该视图将保留该识别器,没有保留循环。
[aView addGestureRecognizer:tapRec];

addGestureRecognizer: 文档 中提到,视图会保留识别器。


由于您正在使用ARC,这就是您需要做的全部。

UIGestureRecognizer* tapRec = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
[aView addGestureRecognizer:tapRec];

你在那个页面上找到了哪些信息?肯定不是在 addTarget:action: 下面。 - Meda
缺少信息也是一种信息。在识别器中没有必要保留自身的技术需求。 - vikingosegundo
@Meda,如果识别器会保留目标,则会在文档中说明。 - vikingosegundo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接