Search code examples
iosuikit

Swapping rootViewController on UIWindow does not deallocate view controller


If you swap out a rootViewController in UIWindow, for example, to present a log in window, if the rootViewController has presented (modal) view controllers, those presented view controllers and possibly the old rootViewController will not be deallocated.

self.window.rootViewController = newViewController

Solution

  • You must always do a dismissal of all modals when swapping out the rootViewController, otherwise there will be a retain cycle.

    if window?.rootViewController.presentedViewController != nil {
        window?.rootViewController.dismiss?(animated: false) {
            window?.rootViewController = newViewController
        }
    }
    else {
        window?.rootViewController.dismiss?(animated: false)
        window?.rootViewController = newViewController
    }
    

    If you want to do a nice transition, you could always wrap it in an animation:

    func transition() {
        if window?.rootViewController.presentedViewController != nil {
            window?.rootViewController.dismiss?(animated: false) {
                window?.rootViewController = newViewController
            }
        }
        else {
            window?.rootViewController.dismiss?(animated: false)
            window?.rootViewController = newViewController
        }
    }
    
    UIView.transition(with: window!,
                      duration: 0.3,
                      options: .transitionCrossDissolve,
                      animations: transition)