GCD 中的弱自我,访问自我的 TableView 属性

Weak Self in GCD, accessing TableView property of self

我看到很多这样的代码:

DispatchQueue.main.async {
    self.tableView.reloadData()
}

在这种情况下,tableViewself 的 属性,是否应该确保像这样捕获 weak self

DispatchQueue.main.async { [weak self] in
    self?.tableView.reloadData()
}

我想是的,但是这种类型的“不安全”代码在代码库中非常普遍,我想知道我是否遗漏了什么?

你说:

In this context, where tableView is a property of self, should one instead ensure weak self is captured like this:

DispatchQueue.main.async { [weak self] in
    self?.tableView.reloadData()
}

不,在这种情况下,您实际上不需要使用 weak 引用 self。这里没有持久的强引用循环。最糟糕的情况(在没有 weak 引用的情况下)是它将保持对 self 的强引用,直到分派的块完成 运行ning。但是该关闭通常会立即 运行 并且转瞬即逝的强引用将很快被消除。

因此,不,您不必在此处使用 weak 引用。这样做在技术上并不是不正确的,但实际上增加了句法噪音而没有任何好处。是的,我们应该努力用 weak 引用来打破潜在的强引用循环,但这不是其中一种情况。


顺便说一句,“不安全”一词的选择有点混淆了话题。 “不安全”在谈到内存引用时有一个非常具体的含义:它通常是指在不使用 运行 时间安全检查时对已释放对象的悬挂引用。正如 The Swift Programming Language: Automatic Reference Counting 所说(原文强调):

Swift also provides unsafe unowned references for cases where you need to disable runtime safety checks—for example, for performance reasons. As with all unsafe operations, you take on the responsibility for checking that code for safety.

You indicate an unsafe unowned reference by writing unowned(unsafe). If you try to access an unsafe unowned reference after the instance that it refers to is deallocated, your program will try to access the memory location where the instance used to be, which is an unsafe operation.

显然,强引用和弱引用都是安全的(前者使对象不被释放,后者在对象释放时将其引用设置为nil)。即使 unowned 引用也经常使用 运行 时间安全检查(尽管如果在对象被释放后使用 unowned 引用,它仍然会导致 运行 时间错误)。在高性能场景中使用“不安全”引用,在这种情况下,您绝对相信您的无主引用会得到妥善处理,并且您愿意 运行 您的代码无需 运行 时间安全检查。

我怀疑你在这个上下文中并不是指“不安全”,但我提到它是为了让你知道这个词在 ARC 和内存管理的上下文中具有非常具体的含义。