RxSwift; ViewController从未取消初始化

时间:2019-08-27 12:17:01

标签: ios swift rx-swift deinit

我有一个ViewController(称为MainViewController),该ViewController由ViewModel(称为MainViewModel)支持。

ViewModel具有一个变量,该变量定义应将哪个子ViewController MainViewController作为其子元素出现。

我的问题是,当一个孩子被取而代之另一个孩子时,它永远不会deinit受过教育。

代码如下:

MainViewController:

class MainViewController: UIViewController {

    var viewModel: MainViewModel!
    private let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()

        viewModel.viewController
            .subscribe(onNext: { [weak self] vc in
                self?.newVc(vc)
            })
            .disposed(by: disposeBag)
    }

    static func instantiate(viewModel: MainViewModel) -> MainViewController {
        let vc = MainViewController()
        vc.viewModel = viewModel
        return vc
    }

    private func newVc(_ vc: UIViewController) {
        remove(childViewController: children.first)
        addFullScreen(childViewController: vc)
    }
}

MainViewModel:

class MainViewModel {

    lazy var viewController: Observable<UIViewController> = {
        return Observable.just(ColorViewController(.green))
            .delay(RxTimeInterval.seconds(3), scheduler: MainScheduler.instance)
            .startWith(ColorViewController(.yellow))
    }()

}

您在MainViewModel的{​​{1}}变量中看到,它首先发出黄色的ColorViewController,然后3秒钟发出绿色的。 viewController是UIViewController的基本子类,具有彩色视图,并且ColorViewController方法被覆盖。删除黄色的ColorViewController时,不会调用此方法。

谁持有对该黄色ColorViewController的引用,以及如何对其进行修复?

奖金代码:

deinit

更新:

因此,我将extension UIViewController { public func addFullScreen(childViewController child: UIViewController) { guard child.parent == nil else { return } addChild(child) view.addSubview(child.view) child.view.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ view.leadingAnchor.constraint(equalTo: child.view.leadingAnchor), view.trailingAnchor.constraint(equalTo: child.view.trailingAnchor), view.topAnchor.constraint(equalTo: child.view.topAnchor), view.bottomAnchor.constraint(equalTo: child.view.bottomAnchor) ]) child.didMove(toParent: self) } public func remove(childViewController child: UIViewController?) { guard let child = child else { return } guard child.parent != nil else { return } child.willMove(toParent: nil) child.view.removeFromSuperview() child.removeFromParent() } } 变量更改为此:

viewController

现在,我看到lazy var viewController: Observable<UIViewController> = { return Observable<Int>.interval(RxTimeInterval.seconds(3), scheduler: MainScheduler.instance) .scan(0, accumulator: { (prev, next) -> Int in return prev + 1 }) .map { index -> UIViewController in let modul = index % 3 print("Index: \(index): \(modul)") switch modul { case 0: return ColorViewController(.yellow, tag: "Yellow") case 1: return ColorViewController(.blue, tag: "Blue") case 2: return ColorViewController(.green, tag: "Green") default: return ColorViewController(.red, tag: "Red") } }.startWith(ColorViewController(.cyan, tag: "Initial 1"), ColorViewController(.purple, tag: "Initial 2")) .take(10) }() 中生成的所有ColorViewController都已按预期进行了初始化。但是传递到.map的两个对象永远不会被初始化,即使.startWith导致Observable完成之后也是如此。这对任何人有意义吗?

1 个答案:

答案 0 :(得分:1)

打开可视内存调试器,以找出谁在保留要释放的视图控制器。这是一篇有关它的文章:https://useyourloaf.com/blog/xcode-visual-memory-debugger/

还有Apple的视频:https://developer.apple.com/videos/play/wwdc2018/416