Search code examples
iosswiftuiviewcontrollerdeinitkeywindow

Swift iOS -View Controller deinit runs when adding it to a new keyWindow


I have a view controller (OrangeVC) that I add to a class that contains a new keyWindow(NewKeyWindowClass). A button in a different vc is tapped and it triggers this new window to get shown over the app's main window and it animates from the right side bottom of the screen to fill to the top. The animation works fine, it starts from the bottom and fills the screen with a new vc with a orange background. The problem is once the OrangeVC is added to the NewKeyWindowClass the orangeVC's deinit keeps getting triggered.

Why is it's deinit running?

Class that goes inside Animator Class:

class OrangeController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = .orange
    }

    deinit {
        print("OrangeVC -Deinit")
    }
}

AnimatorClass:

import UIKit

class NewKeyWindowClass: NSObject {

    func animateOrangeVCFromBottomToTop() {

        guard let keyWindow = UIApplication.shared.keyWindow else { return }

        let orangeVC = OrangeController()

        // 1. starting frame
        orangeVC.view.frame = CGRect(x: keyWindow.frame.width - 10, y: keyWindow.frame.height - 10, width: 10, height: 10)

        keyWindow.addSubview(orangeVC.view)

        UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {

            // 2. ending frame
            orangeVC.view.frame = keyWindow.frame
        })
    }
}

Button from a different class that triggers the animation:

@IBAction func triggerAnimationButtonPressed(_ sender: UIButton) {
    let newKeyWindowClass = NewKeyWindowClass()
    newKeyWindowClass.animateOrangeVCFromBottomToTop()
}

Solution

  • I got the answer from this reddit

    An iOS application must have a rootViewController, create one and set the keyWindow.rootViewController property to it. Then present your view controller from that. Or just the rootViewController to be your View Controller actually.

    The reason the RedVC kept running it's deinit was because the keyWindow didn't have a rootViewController. I added the RedVC's view as a subview to the keyWindow keyWindow.addSubview(orangeVC.view) instead of making it it's rootVC:

    keyWindow.rootViewController = redVC
    

    Once I added it that the RedVC's deinit no longer ran when the animation occurred.

    It should be noted that although it stopped the deinit from running I lost the animation and it also made the original keyWindow disappear. I should actually add this to a different UIWindow.