【问题标题】:'[weak self]' in RXSwift closuresRXSwift 闭包中的“[weak self]”
【发布时间】:2016-05-02 09:31:58
【问题描述】:

我需要在 RXSwift subscribeNext 闭包中使用 [weak self] 吗?

我有代码:

    searchController.searchBar.rx_text.throttle(0.2, scheduler: MainScheduler.instance).subscribeNext { searchText in
        self.viewModel.searchForLocation(searchText)
    }.addDisposableTo(DisposelBag.sharedDisposelBag.disposeBag)

我是否需要修改它,以便在关闭的开头有一个[weak self] 捕获列表?像这样:

    searchController.searchBar.rx_text.throttle(0.2, scheduler: MainScheduler.instance).subscribeNext { [weak self] searchText in
        self?.viewModel.searchForLocation(searchText)
    }.addDisposableTo(DisposelBag.sharedDisposelBag.disposeBag)

【问题讨论】:

标签: swift closures rx-swift


【解决方案1】:

如果闭包不属于该类,则不必使用[weak self]

在内联闭包的情况下,闭包不属于类,而是属于它的作用域,并且在离开作用域时将被释放。

如果传入闭包,它可能属于也可能不属于类(例如属性),谨慎使用 [weak self] 以防它属于类。

【讨论】:

  • 你的回答有点混乱。如果闭包由作用域拥有,例如函数,则在调用该函数后将永远不会调用闭包。闭包归您正在观察的对象所有,在这种情况下为searchBar。因此,如果 self 以某种方式对 searchBar 有强引用,则 OP 应该使用 weak
  • 你能举个例子吗?
【解决方案2】:

是的,如果您在闭包内访问self,您应该创建一个对self 的弱捕获,并且self 可能会在调用闭包之前变为nil

如果闭包捕获self,然后self 变为nil,当调用闭包并尝试访问self 时,您将收到异常。

感谢 scotteg,他在 GitHub 上有一个示例项目:https://github.com/scotteg/TestRxSwiftClosures

参见示例中的DetailViewController

您可以取消注释其他两个示例,一次一个,以查看结果。第一个根本没有定义捕获列表,第二个定义了unowned 捕获。运行应用程序并输入一些文本,然后在 5 秒内点击完成(每次关闭有 5 秒延迟)。前两个示例将导致抛出异常。

基本规则是这样的:如果捕获(例如self)可以设置为nil,例如如果它引用的实例被释放,则将捕获定义为weak。否则,如果闭包和闭包内的捕获将​始终​相互引用并同时被释放,则将捕获定义为unowned

【讨论】:

  • 这个例子很容易引起误解,因为在这种情况下 RxSwift 不是问题,而是Async.main 调用。如果你要使用 RxSwift 的 delay 运算符,你就不会遇到这个问题,你可以安全地使用 [unowned self]
【解决方案3】:

如果存在强引用循环,您将需要使用 [unowned self][weak self]。闭包内的变量可以由闭包“拥有”,如果闭包是,它们会一直存在,所以这就是我们使用[unowned self][weak self] 的原因。

【讨论】:

    【解决方案4】:

    [unowned self] 表示当block被调用时self不能为nil。如果block被调用并且self为nil,则应用程序崩溃。

    [weak self] 表示当调用块时 self 可以为 nil。因此,您必须在块内处理可选的 self。

    所以,我的快速回答是 1.当您在视图控制器块中引用视图模型时,请始终使用[unowned self],因为您可以确保视图模型始终存在于其关联的视图控制器中。

    2.在其他情况下,当你在一个块中使用 self 时总是会被提醒。根据 self 是否可以为 nil 来选择 unowned 和 weak。

    【讨论】:

    • 谢谢你,????
    猜你喜欢
    • 2015-09-04
    • 2015-07-02
    • 1970-01-01
    • 2019-12-03
    • 2021-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多