RxSwift:当类具有 disposeBag 属性时,始终使用 [unowned self] 是不是安全?

Posted

技术标签:

【中文标题】RxSwift:当类具有 disposeBag 属性时,始终使用 [unowned self] 是不是安全?【英文标题】:RxSwift: Is it safe to always use [unowned self] when a class has a disposeBag property?RxSwift:当类具有 disposeBag 属性时,始终使用 [unowned self] 是否安全? 【发布时间】:2017-10-20 07:19:31 【问题描述】:

我最近发现一篇文章说使用[unowned self] 总是安全的,只要您将订阅添加到DisposeBag 并且它位于视图控制器内。

假设我有一个 ViewController,其中 deinit 由于强引用而没有被调用:

class ViewController: UIViewController 

    @IBOutlet weak var searchBar: UISearchBar!
    @IBOutlet weak var tableView: UITableView!

    private let disposeBag = DisposeBag()
    private var results = Variable<[Item]>([])
    private var searchText = Variable("")
    var selectedCompletion: ((Item) -> Void)!

    override func viewDidLoad() 
        super.viewDidLoad()
        results.asObservable()
            .bind(to: tableView.rx.items(cellIdentifier: "CustomCell", cellType: CustomCell.self))  row, item, cell in
                cell.configure(with: item)
            
            .disposed(by: disposeBag)

        tableView.rx.itemSelected
            .subscribe(onNext:  ip in
                self.selectedCompletion(self.results.value[ip.row])
                self.navigationController?.popViewController(animated: true)
            )
            .disposed(by:disposeBag)

        searchBar.rx.text
            .debounce(0.6, scheduler: MainScheduler.instance)
            .subscribe(onNext:  searchText in
                if searchText == nil || searchText!.isEmpty  return 
                self.search(query: searchText!)
            )
            .disposed(by: disposeBag)
    

    private func search(query: String) 
        // Search asynchronously
        search(for: query)  response in

            // Some logic here...
            self.results.value = searchResult.results
        
    

我应该能够简单地在订阅关闭时声明[unowned self],而不必担心我的应用程序会从self 变为nil 崩溃。

我感到困惑的是,因为搜索是异步的,如果在查询完成之前 ViewController 已从导航堆栈中弹出,这是否意味着 self 可以nil

或者disposeBag 会先被释放而关闭不会完成?

任何关于如何知道一个类是否拥有闭包的说明也很好。

【问题讨论】:

我想你不能确定。这取决于内部实现和线程竞争。例如,如果 http 客户端捕获了您的闭包并调用了请求,那么即使 disposeBag 取消订阅,仍然可能存在竞争条件,并且 http 客户端可能会在处理 self 后立即调用您的闭包。 【参考方案1】:

根据我的经验,将 unowned 与处置袋一起使用是一种安全的方法,除了一个块 - onDisposed。有一些应用程序因为 unowed 关键字而崩溃的情况 -> weak 在这里很有用。

【讨论】:

【参考方案2】:

正如@kzaher 在 github 上所说的那样

你永远不应该使用 unowned。

来源:

https://github.com/RxSwiftCommunity/RxDataSources/issues/169 https://github.com/ReactiveX/RxSwift/issues/1593

【讨论】:

以上是关于RxSwift:当类具有 disposeBag 属性时,始终使用 [unowned self] 是不是安全?的主要内容,如果未能解决你的问题,请参考以下文章

在 RxSwift 中手动处理 DisposeBag

RxSwift:disposed(by: disposeBag) 真的有效吗?

ViewController 中的 RxSwift DisposeBag 使用

如何使用 RxSwift disposeBag 防止 UITableViewCell 中重复的 UIButton 点击

RxSwift 系列

谁应该在 Swift 上将 DisposeBag 保留在 MVVM(+controller) 中