1

例如:

[self.contentWrapperView addGestureRecognizer:
   [UITapGestureRecognizer recognizerWithHandler:^(UIGestureRecognizer *sender, 
                                                   UIGestureRecognizerState state, 
                                                   CGPoint location) {
        if (self.customEditing) {
        [self setEditingMode:NO Animated:YES];
      }
    }]];

WherecontentWrapperView是 上的一个强属性self,并且假定contentWrapperView对识别器块有一个强引用。在块中使用self会导致保留周期吗?这是唯一我不太明白的部分。

4

2 回答 2

4

是的,它会导致一个保留周期。

万一您关心的解决方法是

__weak id weakSelf = self;
[self.contentWrapperView addGestureRecognizer:[UITapGestureRecognizer recognizerWithHandler:^(UIGestureRecognizer *sender, UIGestureRecognizerState state, CGPoint location) {
    if ([weakSelf customEditing]) {
        [weakSelf setEditingMode:NO Animated:YES];
    }
}]];
于 2013-03-26T20:51:11.080 回答
4

根据实际情况考虑保留周期:您拥有的对象保留您自己。

用 Cocoa 和 Cocoa-Touch 的术语来说,这意味着你强烈拥有的任何变量都不能反过来强烈拥有。这通常通过声明需要拥有其父级的属性来解决weakunsafe_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.
}]];
于 2013-03-26T21:06:44.053 回答