【问题标题】:Using method with self inside blocks在块内使用带有 self 的方法
【发布时间】:2014-06-26 11:10:45
【问题描述】:

我需要在两个块中执行相同的一堆代码(我正在使用 ARC):

__weak typeof(self) weakSelf = self;
[_dataProvider doA:^(NSError *error) {
    [weakSelf handleError:error];
}];

我在另一个地方打电话:

__weak typeof(self) weakSelf = self;
[_dataProvider doB:^(NSError *error) {
    [weakSelf handleError:error];
}];

然后我有我的处理程序:

- (void)handleError:(NSError *)error {
    [self.refreshControl endRefreshing];
    [self.tableView reloadData];
}

这样使用省钱吗?请注意handleError: 方法在内部使用self。如果不是,那么这里的正确方法是什么?顺便说一句:self 是一个 viewController,可以解除分配(doB: 和 doA: 块是基于网络的,所以可能很慢)。

【问题讨论】:

  • 你是什么意思使用安全?它不会炸毁你的设备...所以,是的,在那个视图中它是安全的。
  • 这不是“完全”安全的,请看我的回答。

标签: objective-c block retain-cycle


【解决方案1】:

这样做并不安全,即使很多人都这样做。

在合理的情况下,您应该使用带有块的“weakSelf”模式。 在您的示例中,“weakSelf”模式是不合理的,因为self 没有任何strong 引用您的block。你可以这样使用:

[_dataProvider doA:^(NSError *error) {
    // here you can use self, because you don't have any strong reference to your block

    [weakSelf handleError:error];
}];

如果您有一个 strong 对您的 block 的引用(例如带有属性或实例变量)并且您在 block 中捕获 self,则使用“weakSelf”模式,例如:

 @property(strong) void(^)(void) completionBlock;
....

__weak typeof(self) weakSelf = self; 

    self.completionBlock = ^{
      // Don't use "self" here, it will be captured by the block and a retain cycle will be created
      // But if we use "weakSelf" here many times, it risques that it will be nil at the end of the block
      // You should create an othere strong reference to the "weakSelf"
      __strong typeof(self) strongSelf = weakSelf; 
      // here you use strongSelf ( and not "weakSelf" and especially not "self")
    };

【讨论】:

  • 我听说过类似的事情。然而,据我所知,xCode 不同意这一点-[_someInstance doC:^(NSError *error) { self.index += 5; }];(其中@property (nonatomic, assign) NSInteger index;)。 XCode 声明Capturing 'self' strongly in this block is likely to lead to a retain cycle。我既没有这个块的属性也没有 ivar,为什么我会收到警告?
  • 我将通过执行以下操作使警告静音:#pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-retain-cycles" ....你的块在这里 #pragma clang diagnostic pop
  • 所以你声称这是一个一般性警告,在这种特定情况下我不应该关心它?我通常发现警告很有帮助,我担心警告背后隐藏着一些“真相”。但是,如果您确定在这种情况下没问题,那么我了解它的工作原理。
猜你喜欢
  • 2014-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多