简体   繁体   English

RxSwift; ViewController 从未取消初始化

[英]RxSwift; ViewController never deinitialized

I have a ViewController (called MainViewController ) which is backed by a ViewModel (called MainViewModel ).我有一个视图控制器(称为MainViewController这是由一个视图模型(称为支持) MainViewModel )。

The ViewModel has a variable that defines which child ViewController MainViewController should present as its child. ViewModel 有一个变量,用于定义哪个子 ViewController MainViewController应该作为其子项出现。

My problem is that, when a child is removed in favor of another child, it never gets deinit 'ed.我的问题是,当一个孩子为了另一个孩子而被移除时,它永远不会被deinit

Here's the code:这是代码:

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))
    }()

}

You see in MainViewModel s viewController variable, that it first emits a yellow ColorViewController, and 3 seconds later a green one.您在MainViewModelviewController变量中看到,它首先发出一个黄色的 ColorViewController,3 秒后发出一个绿色的。 ColorViewController is a basic subclass of UIViewController, with a colored view, and a the deinit -method overwritten. ColorViewController是 UIViewController 的基本子类,带有彩色视图,并覆盖了deinit方法。 This methods isn't called, when the yellow ColorViewController is removed..当黄色的 ColorViewController 被移除时,不会调用此方法。

Who holds the reference to that yellow ColorViewController, and how to fix it?谁持有对该黄色 ColorViewController 的引用,以及如何修复它?

Bonus code:奖金代码:

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()
    }
}

UPDATE:更新:

So I changed the viewController -variable to this:所以我将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)
    }()

Now I see that all the ColorViewController 's generated in the .map are deinitialized as expected.现在我看到在.map中生成的所有ColorViewController都按预期ColorViewControllerColorViewController But the two passed into .startWith , are never deinitialized, not even after .take(10) causes the Observable to complete.但是传入.startWith的两个.startWith永远不会被.startWith ,即使在.take(10)导致 Observable 完成之后也不会。 Does that make sense to anyone?这对任何人都有意义吗?

Open up the visual memory debugger to find out who is holding on to the view controller that you want to have released.打开可视化内存调试器,找出谁在持有你想要释放的视图控制器。 Here is an article about it: https://useyourloaf.com/blog/xcode-visual-memory-debugger/这是一篇关于它的文章: https : //useyourloaf.com/blog/xcode-visual-memory-debugger/

And a video from Apple: https://developer.apple.com/videos/play/wwdc2018/416以及来自 Apple 的视频: https : //developer.apple.com/videos/play/wwdc2018/416

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM