【问题标题】:Is weak self needed in NSKeyValueObservation observe() closure?NSKeyValueObservation observe() 闭包中是否需要弱自我?
【发布时间】:2018-03-18 11:27:57
【问题描述】:

我有:

private var statusLabel:   UILabel!
private var errorObserver: NSKeyValueObservation?

self.errorObserver = self.viewModel.observe(\.errorString)
{ [weak self] (viewModel, change) in
    self?.statusLabel.text = viewModel.errorString
}

这里需要[weak self]吗?

【问题讨论】:

  • 没有[weak self],你就有一个保留周期。这可能是可接受的或想要的(如果您最终明确删除观察者)或不。
  • @MartinR 这种新的 (Swift 4 / Xcode 9) KVO 形式不再需要在 deinit 中显式删除观察者。这不会改变事情吗?
  • 我不这么认为(也许我忽略了一些东西!)。您可以通过将deinit { print("deinit") } 添加到您的观察类中来轻松检查它,看看它是否被调用。

标签: swift swift4 key-value-observing


【解决方案1】:

简短回答:是的,您确实需要[weak self]。不必显式删除 deinit 中的观察者是一个很好的便利,它可以确保观察中心不会向取消初始化的观察者发送通知,但不会免除您必须为关闭管理内存。

Apple 的官方文档(The Swift Programming Language 4.0.3)声明:

默认情况下,闭包表达式从其周围作用域捕获常量和变量,并对这些值进行强引用。您可以使用捕获列表来显式控制如何在闭包中捕获值。

一个捕获列表被写成一个逗号分隔的表达式列表,用方括号括起来,在参数列表之前。如果使用捕获列表,则还必须使用 in 关键字,即使省略参数名称、参数类型和返回类型也是如此。

....

如果表达式的值的类型是类,您可以在捕获列表中用弱或无主标记表达式,以捕获对表达式值的弱或无主引用。

Excerpt From: Apple Inc. “The Swift Programming Language (Swift 4.0.3).” iBooks.

如果您不在捕获列表中标记表达式self,则会创建一个强引用循环。因为类是引用类型,而闭包是引用类型,所以创建了一个强引用循环。当闭包的主体引用类的实例时,闭包会创建对类实例的引用。默认情况下,这是一个强引用,除非您使用捕获列表来定义不同类型的引用。官方注释偶say

当您在闭包中引用self 的成员时,Swift 要求您编写self.somePropertyself.someMethod()(而不仅仅是somePropertysomeMethod())。这有助于您记住可能会意外捕获self

在您的情况下,您引用的是闭包主体内的标签。你需要写的事实

self?.statusLabel.text = viewModel.errorString

而不是简单

.statusLabel.text = viewModel.errorString

提示您在捕获列表中使用self

【讨论】:

    猜你喜欢
    • 2021-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多