How do I toggle between UIWindows?

2019-09-16 09:38发布

问题:

Scenario:

I've created an overlay window (with tag = 100) that I eventually want to dismiss. But the following code doesn't work:

UIApplication.shared.windows.first?.becomeKey()
UIApplication.shared.windows.last?.resignKey()


(lldb) po UIApplication.shared.windows
▿ 2 elements
  - 0 : <UIWindow: 0x7fa698d0ad00; frame = (0 0; 768 1024); gestureRecognizers = <NSArray: 0x600000048550>; layer = <UIWindowLayer: 0x6000000278a0>>
  - 1 : <UIWindow: 0x7fa698d14bb0; frame = (0 0; 768 1024); autoresize = W+H; tag = 100; gestureRecognizers = <NSArray: 0x600000252a50>; layer = <UIWindowLayer: 0x600000229660>>

Any ideas to either toggle or delete the overlay window?

回答1:

Simply set the window's isHidden property to true:

var overlayWindow: UIWindow?
...
overlayWindow?.isHidden = true
overlayWindow = nil  // optional

If you set any references to this window to nil, the window will be disposed.

Please also note that you are not supposed to call resignKey(). From its documentation (emphasis mine):

Discussion
Never call this method directly. The system calls this method and posts UIWindowDidResignKey to let the window know when it is no longer key. The default implementation of this method does nothing, but subclasses can override it and use it to perform tasks related to resigning the key window status.

The same is true for becomeKey(), by the way. You probably want to use makeKey() or makeKeyAndVisible().



回答2:

This is essentially a two-part question.

  1. How do I display a created UIWindow and
  2. How do I dismiss it?

I learned that I have to keep a reference to the newly-created UIWindow rather than merely have local-scope reference. ...which is obvious.

Once I have a persistent reference to the ancillary UIWindow, I can merely assign nil to it to remove it:

var hamburgerWindow:UIWindow?

 @IBAction func displayOverlayWindowAction() {
     guard hamburgerWindow != nil else {
         displayOverLay()
         return
     }
     hamburgerWindow = nil
 }