Objective-C正确使用ARC的块?

时间:2012-06-26 16:30:24

标签: objective-c automatic-ref-counting block objective-c-blocks

我知道之前已经问过这个问题,但是没有解决方案可以解决我的问题,所以我再次问这个问题。我试图通过块回调来调用self上的方法。我收到以下错误:

在此区块中强烈捕捉'自我'可能会导致保留周期

- (void)viewDidLoad {
   [super viewDidLoad];

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

我尝试过类似下面的代码,我仍然得到同样的警告。 解决方案是什么?

__weak id myself = self;
[myself populateData];  

2 个答案:

答案 0 :(得分:4)

您的代码应如下所示:

- (void)viewDidLoad {
   [super viewDidLoad];

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

答案 1 :(得分:0)

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

首先,你为什么得到警告?

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

写作的尝试

__weak id myself = self;
[myself populateData];  

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

UIAdam的写作解决方案

__弱id weakSelf = self;    self.webClient.completionHandler = ^ {       [weakSelf populateData];    };

表示weakSelf是弱引用,并且该块仅包含对self的弱引用。因此,如果所有其他强烈的自我引用都消失了,那么只剩下一个弱引用。弱引用并不能保持自我活动,因此自我被释放。

现在如果发生这种情况会怎么样,但是其他东西对webClient有强烈的引用并且你的块被调用了? weakSelf是一个弱引用,当对象被释放时,弱引用被设置为nil。因此,当你的块被调用时,你必须准备好weakSelf为nil。写

实际上更好
id strongSelf = weakSelf;
[strongSelf populatedData];
块内的

:strongSelf可能设置为nil,或者它将设置为self。但由于它是一个强大的参考,它将保持非零,直到块完成。如果开始时不是零。