0

我知道以前有人问过这个问题,但是没有一个解决方案可以解决我的问题,所以我再次问这个问题。作为通过块回调的结果,我试图在 self 上调用一个方法。我收到以下错误:

在此块中强烈捕获“自我”可能会导致保留周期

- (void)viewDidLoad {
   [super viewDidLoad];

   self.webClient.completionHandler = ^{
      [self populateData];
   };
}

我尝试做类似下面代码的事情,但我仍然收到同样的警告。解决方案是什么?

__weak id myself = self;
[myself populateData];  
4

2 回答 2

4

您的代码应如下所示:

- (void)viewDidLoad {
   [super viewDidLoad];

   __weak id weakSelf = self;
   self.webClient.completionHandler = ^{
      [weakSelf populateData];
   };
}
于 2012-06-26T16:38:31.023 回答
0

UIAdam 给出了正确的答案,但值得理解为什么它是正确的。

首先,您为什么收到警告?

self 对 webClient 有很强的引用。webClient 对 completionHandler 有很强的引用。completionHandler 对 self 有很强的引用。因此,如果您的程序中的所有其他引用都消失了,那么在这个循环中仍然存在对每个项目的强引用,因此它们永远不会被释放。

写作的尝试

__weak id myself = self;
[myself populateData];  

当然不起作用。该块仍然引用自我,因为它正在将它分配给我自己。所以这里没有区别。

UIAdam 的写作解决方案

__weak id 弱自我 = 自我;self.webClient.completionHandler = ^{ [weakSelf populateData]; };

表示weakSelf是一个弱引用,block只包含一个对self的弱引用。因此,如果所有其他对 self 的强引用都消失了,则只剩下一个弱引用。弱引用不会使 self 保持活动状态,因此 self 会被释放。

现在如果发生这种情况,但是其他东西对 webClient 有很强的引用并且你的块被调用了怎么办?weakSelf 是一个弱引用,当对象被释放时,弱引用被设置为 nil。所以你必须做好准备,当你的块被调用时,weakSelf 为零。实际上写得更好

id strongSelf = weakSelf;
[strongSelf populatedData];

块内部:strongSelf 可能设置为 nil,或者将设置为 self。但由于它是一个强引用,所以在块完成之前它将保持非零。如果它不是零开始的。

于 2014-04-03T15:35:36.900 回答