【发布时间】: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 后立即调用您的闭包。