Я читал об этом в блоге 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)
, а компилятор выдает предупреждение.
![enter image description here](https://i.stack.imgur.com/CM847.png)
Затем я начал смотреть на реализацию subscribe(onNext:...)
(с / п ниже):
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
содержит строгую ссылку на disposable
через лямбда-функцию.Однако чего я не понимаю, так это то, как disposable
содержит строгую ссылку на observer
?