我从博客帖子http://adamborek.com/memory-managment-rxswift/中了解到这一点:
当您订阅
Observable
时,Disposable
保留对Observable
的引用,而Observable
保留对Disposable
的强烈引用(Rx创建某种保留周期)。因此,如果用户在导航堆栈中导航,除非您希望将Observable
释放,否则将不会被释放。
仅出于理解的目的,我创建了这个虚拟项目:在哪里有一个视图,在视图的中间,有一个巨大的按钮,它将发出有关该按钮被点击多少次的事件。就那么简单。
import UIKit
import RxCocoa
import RxSwift
class Button: UIButton {
private var number: Int = 0
private let buttonPushedSubject: PublishSubject<Int> = PublishSubject.init()
var buttonPushedObservable: Observable<Int> { return buttonPushedSubject }
deinit {
print("Button was deallocated.")
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
}
@objc final func buttonTapped() {
number = number + 1
buttonPushedSubject.onNext(number)
}
}
class ViewController: UIViewController {
@IBOutlet private weak var button: Button!
deinit {
print("ViewController was deallocated.")
}
override func viewDidLoad() {
super.viewDidLoad()
button.buttonPushedObservable.subscribe(onNext: { (number) in
print("Number is \(number)")
}, onError: nil, onCompleted: nil, onDisposed: nil)
}
}
令人惊讶的是,在关闭此视图控制器后,日志如下所示:
Number is 1
Number is 2
Number is 3
Number is 4
ViewController was deallocated.
Button was deallocated.
...
,这意味着ViewController
和Button
已被释放!在这种情况下,我没有调用disposeBy(bag)
并且编译器发出警告。
然后,我开始研究subscribe(onNext:...)
的实现(以下c / p):
let disposable: Disposable
if let disposed = onDisposed {
disposable = Disposables.create(with: disposed)
}
else {
disposable = Disposables.create()
}
let callStack = Hooks.recordCallStackOnError ? Hooks.customCaptureSubscriptionCallstack() : []
let observer = AnonymousObserver<E> { event in
switch event {
case .next(let value):
onNext?(value)
case .error(let error):
if let onError = onError {
onError(error)
}
else {
Hooks.defaultErrorHandler(callStack, error)
}
disposable.dispose()
case .completed:
onCompleted?()
disposable.dispose()
}
}
return Disposables.create(
self.asObservable().subscribe(observer),
disposable
)
在上面的代码块中,确实observer
通过lambda函数拥有对disposable
的强烈引用。但是,我不明白的是,disposable
是如何强烈引用observer
的?
答案 0 :(得分:1)
可观察对象处于活动状态时,存在一个参考周期,但是按钮的取消分配会发送一个完整事件,从而中断该周期。
也就是说,如果您执行类似Observable<Int>.interval(3).subscribe()
的操作,则流将不会取消分配。
仅在源完成/错误或在生成的一次性对象上调用dispose()时,才流关闭(因此取消分配)流。使用上面的代码行,源(interval
)将永远不会完成或出错,并且未保留对一次性对象的引用,因此无法在其上调用dispose()。
想到它的最好方法是... complete
/ error
是源告诉接收器它已经完成发射的方式(这意味着不再需要该流)。并在一次性对象上调用dispose()
是一种接收者的方式,它告诉消息源它不希望接收更多事件(这也意味着不再需要该流)。为了取消分配该流,可以源或汇需要报告已完成。
要明确回答您的问题...您不需要将一次性用品添加到处理袋中,但是如果视图控制器删除而不进行处理并且源未发送完整的消息,流将泄漏。因此,为了安全起见,请确保在处理完流后将水槽丢弃。