__weak self 可以在块中间变成 nil 吗?

Can __weak self turn nil in the middle of the block?

在后台线程上运行的块中使用 __weak self 引用时,我是否只需要在开始时检查 nil,或者 __weak self 即使在第一个 nil 测试通过后执行期间也变为 nil?我想从块中的 self 访问一些 ivar,我需要块执行时的最新值。

如果没有人持有对 self 的引用,那么是的。您可以通过在块

中使用强引用来缓解这种情况
__weak __typeof(self) weakSelf = self;

^{
  __strong __typeof(weakSelf) strongSelf = weakSelf;
  if (!strongSelf) {
    return;
  }
};

您可以通过从块内部强引用它来避免将引用设置为 nil。

在块内获取对弱指针的强引用。

__weak MyObject *weakSelf = self; // a weak reference
myBlock = ^{
  MyObject *innerSelf = weakSelf; // a block-local strong reference
  NSLog(@"MyObject: %@", innerSelf); 
};

避免直接使用变量,因为这会导致循环引用。 如果直接在块中使用实例变量,块将捕获 self,因此您必须使用它们的访问器来引用实例变量。

__weak MyObject *weakSelf = self;
myBlock = ^{
    MyObject *innerSelf = weakSelf; // a block-local strong reference
    NSLog(@"MyObject: %@", innerSelf);
    NSLog(@"MyObject ID: %d", innerSelf.objectID);
};

如果像这样直接使用实例变量:

NSLog(@"MyObject ID: %d", _objectID);

编译器将 _objectID 解释为 self->_objectID,其中 self 被您的块捕获。

弱引用的本质是,当最后一个强引用在另一个线程中被删除时,它可以随时变为 nil。如果你访问成员变量,这是致命的,因为你会崩溃,如果你调用那个弱变量的方法,这是致命的,因为 self 是不安全的未保留的。

有一种每个人都在使用的解决此问题的简单方法:在执行任何操作之前将弱变量存储到字符串 one 中,无需任何检查。然后检查 strong 变量是否为 nil;该检查需要一次

在Xcode中打开所有警告,这样如果你做了任何危险的事情就会得到警告。