【问题标题】:When to use [self] vs [weak self] in swift blocks?何时在 swift 块中使用 [self] 与 [weak self]?
【发布时间】:2020-10-23 17:11:36
【问题描述】:

[self] 是一个新术语,我们可以在块中使用它来避免使用 self 关键字。那么这和[weak self] 有什么不同呢? [self] 是否负责保留周期?

我找不到太多这方面的信息,所以任何简单的解释示例都将受到高度赞赏。

【问题讨论】:

  • [self] 是强捕获,而 [weak self] 是弱捕获。这只是为了方便而不是在闭包中使用 self. 前缀
  • proposal 本身应该很好地涵盖了这些更改。
  • 感谢您的回答。我有点困惑,为什么我要在块内使用强捕获[self],因为有内存泄漏的机会,[weak self] 可以让我们免于这种情况?
  • 在某些情况下需要强大的捕获者 - 即当您希望闭包在对象执行之前保持活动状态时。
  • 创建保留周期时可能会发生泄漏。如果self 拥有闭包,并且闭包强烈捕获self,则闭包和self 都不能从内存中释放。通常,循环并不那么直接。例如self 拥有一个服务,该服务拥有一个拥有 self 等的闭包。

标签: swift


【解决方案1】:

[self] 表示self 是有意保留的强引用(因此简化了一些语法)。 [weak self] 表示 self 被弱引用持有。

为什么我要在块内使用强捕获[self],因为有内存泄漏的机会

当您知道没有参考周期或希望有一个临时参考周期时,您可以使用它。捕获self 本身不会创建循环。必须有一个循环。您可能从您的代码中知道没有。例如,持有闭包的东西可能被其他对象持有(而不是self)。良好的组合(以及将复杂类型分解为更小的类型)很容易导致这种情况。

或者,您可能想要一个临时循环。此 URLSessionTask 最常见的情况。这些文档在这里非常有价值(强调):

创建任务后,通过调用它的 resume() 方法来启动它。然后会话保持对任务的强引用直到请求完成或失败;您不需要维护对任务的引用,除非它对您应用的内部簿记有用。

另一个常见的例子是 DispatchQueue,它类似地持有一个闭包直到它完成。到那时,它释放它,终止循环并允许一切释放。当有意使用时,这是有用且强大的(并且很常见!)。意外使用时,它是错误的来源。所以 Swift 要求你陈述你的意图并试图让情况变得明确。

当您构建自己的保留完成处理程序的类型时,您也应该强烈考虑这种模式。调用完成处理程序后,将其设置为 nil(或 {_ in } 用于非可选)以释放完成处理程序可能引用的任何内容。

当前情况的一个令人沮丧的影响是开发人员不假思索地将[weak self] 打到闭包上。这与预期的相反。看到self 应该会导致开发人员停下来思考参考图。我不确定它是否真的实现了这一点,但作为一个 Swift 程序员,你应该明白这就是意图。这不仅仅是随机语法。

【讨论】:

  • 哇,非常感谢 Rob。这真是一个很好的解释。我一直对 URLSessionTaskDispatchQueue 使用 [weak self] 有疑问,你说得很清楚。
猜你喜欢
  • 2017-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-04
  • 2016-05-02
  • 1970-01-01
  • 2015-07-02
  • 1970-01-01
相关资源
最近更新 更多