Search code examples
iosswiftreactive-programmingrx-swiftrx-cocoa

why deinit of view controller is not calling using RXSwift?


I tried a few things but couldn't find a solution. I am navigating the controller in the onNext block but the deinit is not calling. I have also declared the self as weak in the rx closures.

Below is the complete class code. Please correct if I am doing anything wrong:

class LoginVC: UIViewController {

    //MARK:- Variables & Consts
    private let tag = "LoginVC"
    private let loginViewModel = LoginViewModel()
    private let disposeBag = DisposeBag()
    
    //MARK:- IBOutlets
    @IBOutlet weak var tfUsername: MFTextField!
    @IBOutlet weak var tfPassword: MFTextField!
    @IBOutlet weak var btnLogin: UIButton!
    
    //MARK:- View Controller Life Cycle
    override func viewDidLoad() {
        super.viewDidLoad()
        
        setupBindings()
    }
    
    ///deinit
    deinit {
        print(" deinit")
    }
    
    //MARK:- Custom Methods
    
    private func setupBindings() {
        loginViewModel
            .loginResponse
            .observeOn(MainScheduler.instance)
            .subscribe(onNext: { [weak self] loginResponse in
             let vc = UIStoryboard(name: Constants.MAIN, bundle: nil).instantiateViewController(withIdentifier: Constants.HOME_VC)
                self?.navigationController?.pushViewController(vc, animated: true)
            }, onError: { [weak self] error in
                self?.removeLoader()
            }, onCompleted: {  [weak self]  in
                self?.removeLoader()
            }, onDisposed: { [weak self] in
                print("\(self?.tag ?? "") onDisposed")
            })
        .disposed(by: disposeBag)
        
        btnLogin.rx.tap.bind{ [weak self] in
            self?.loginViewModel.login(username: self?.tfUsername.text ?? "", password: self?.tfPassword.text ?? "")
        }.disposed(by: disposeBag)
    }
}

Any help would be appreciated.


Solution

  • You are pushing the next view controller here.

    self?.navigationController?.pushViewController

    When you do this, LoginVC never gets deallocated because it's still in the memory and navigation controller's stack. So there's no reason for deinit to be called.

    deinit will only get called if you dismiss LoginVC. And if your LoginVC is your root viewcontroller it will never call it's deinit. This has nothing to do with RxSwift.