Search code examples
iosswiftuiviewcontrolleruiwindow

Swift iOS -How to Switch / Toggle between two UIWindows and make either the keyWindow


I created an additional UIWindow that will get presented on top of the main window. The user presses a button and it transitions over the main window. The user can minimize the additional window and it will sit above the tabBar like it the picture below. They can enlarge it to cover the main window or dismiss it and it gets destroyed. It works fine.

I also created a custom action sheet that launches from the bottom of the screen. If the additional window completely covers the main window and the action sheet is launched, it will launch perfectly inside the additional window. If the additional window isn't on the screen it launches perfectly inside the main window.

The problem is if the additional window is minimized on screen and I want to launch the action sheet from the main window, the action sheet launches inside the additional window instead, it cannot distinguish between the two. I opened up the 3D visualizer and it showed that the main window was off and the additional window was on.

How can I distinguish between both windows when displaying the custom action sheet?

Btw if both windows are present and the action sheet is launched from the main window I hide the additional window. I also looked at other answers and they said to use UIApplication.shared.keyWindow.addSubview which I'm already doing.

CustomActionSheet Class:

var collectionView: UICollectionView!
var deltaY: CGFloat!
let height: CGFloat = 200 // 4 cells x 50 pts each

func displayActionSheet(){

     if let window = UIApplication.shared.keyWindow {

         // collectionView initialized...
         window.addSubview(collectionView)

         deltaY = window.frame.height - height

         collectionView.frame = CGRect(x: 0, y: window.frame.height, width: window.frame.width, height: height)

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

             self.collectionView.frame = CGRect(x: 0, y: deltaY, width: self.collectionView.frame.width, height: self.collectionView.frame.height)
         }
      }
}

MainView Class:

@IBAction func mainWindowActionSheetButton(_ sender: UIButton) {

      let customActionSheet = CustomActionSheet()
      customActionSheet.displayActionSheet()
}

AdditionalWindow Class:

let myVC = MyController()
var nav: UINavigationController?
var window: UIWindow!
var maximized = true

override init() {
    super.init()

    window = UIWindow()
    window.backgroundColor = .clear
    window.windowLevel = UIWindowLevelStatusBar
    nav = UINavigationController(rootViewController: myVC)
    window.rootViewController = nav
    window?.isHidden = false
    window?.makeKeyAndVisible()
 }

 func maximizeOrMinimizeWindow() {

    if maximized {
         // show this full screen
    } else {
        // show this window minimized like in the picture
    }
 }

AnotherController Class that has the button that also launches the action sheet:

@IBAction func additionalWindowActionSheetButton(_ sender: UIButton) {

      let customActionSheet = CustomActionSheet()
      customActionSheet.displayActionSheet()
}

window in window

main window

additional window


Solution

  • The summarize the advice in comments.

    The problem is that the action sheet is always shown from the key window but the additional window remains key window even when minimized.

    The obvious solution is to make the main window the key window when the additional one is being minimized. See UIWindow.makeKey() or UIWindow.makeKeyAndVisible().

    Since UIApplication.shared.windows are ordered by window level (the back one first), you can always reach the main window using UIApplication.shared.windows.first.

    Therefore

    UIApplication.shared.windows.first?.makeKey()
    

    will make the main window the key window and the minimized window will stop being the key window.