Multiple Windows
Multiple windows within the same UIscreen.
We can create new window like this.
let frame = UIScreen.main.bounds
let newWindow = UIWindow(frame: CGRect(x: frame.origin.x, y: frame.midY, width: frame.width, height: frame.height/2))
newWindow.isHidden = false
or if we are on iOS 13 and above and have a UIWindowScene
,
guard let refWindow = self.view.window, let scene = refWindow.scene else { return }
let newWindow = UIWindow(windowScene: scene)
newWindow.isHidden = false
make sure we hold window object strongly at application level.
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var additionalWindows: [UIWindow] = []
...
}
so the above window creation code will look like this
let newWindow = UIWindow(frame: CGRect(x: frame.origin.x, y: frame.midY, width: frame.width, height: frame.height/2))
newWindow.isHidden = false
let appDelegate = UIApplication.shared.delegate as? AppDelegate
appDelegate?.additionalWindows.append(newWindow)
Thats it. We have new window in the screen and we can have as many as we want. 🎉
To show content in the new window, use rootViewController
property of UIWindow.
let newRootViewController = UIViewController()
newRootViewController.view.backgroundColor = UIColor.yellow
newWindow.rootViewController = newRootViewController
Animation 🤩
Let's add some animation for new window. Since UIWindow is just a UIView
subclass we can use UIView.animate
methods or UIViewPropertyAnimator
for this.
UIView.animate example
newWindow.alpha = 0
newWindow.frame = CGRect(x: UIScreen.current.frame.midX, y: UIScreen.current.frame.midY, width: 0, height: 0)
UIView.animate(duration: 0.5, options: .curveEaseIn, animation: {
newWindow.frame = CGRect(x: 100, y: 100, width: 200, height: 200)
newWindow.alpha = 1
} { _ in
print("Animation completed")
}
UIViewPropertyAnimator example
let timingParameters = UISpringTimingParameters(dampingRatio: 0.9)
let animator = UIViewPropertyAnimator(duration: 0.5, timingParameters: timingParameters)
animation.addAnimations {
newWindow.frame = CGRect(x: 100, y: 100, width: 200, height: 200)
newWindow.alpha = 1
}
animation.addAnimations ({
newWindow.rootViewController.view.alpha = 1
}, delayFactor: 0.4)
animation.startAnimation()
Remove window 🧹
To remove window, we simply remove it from the additionalWindows
from AppDelegate.
func close(window: UIWindow, animated: Bool = true) {
guard
let appDelegate = UIApplication.shared.delegate as? AppDelegate,
let index = appDelegate.additionalWindows.firstIndex(of: window)
else { return }
func remove() {
window.isHidden = true
appDelegate.additionalWindows.remove(at: index)
}
if animated {
let timingParameters = UISpringTimingParameters(dampingRatio: 0.9)
let animator = UIViewPropertyAnimator(duration: 0.7, timingParameters: timingParameters)
animator.addAnimations {
window.alpha = 0
window.frame = CGRect(x: window.frame.midX, y: window.frame.midY, width: 0, height: 0)
}
animator.addCompletion { _ in
remove()
}
animator.startAnimation()
} else {
remove()
}
}
This will release the rootViewController
for the closing window. So UIViewController life-cycle is maintained. 😎
Notes 📝
UIWindow is just a special UIView.
- has
rootViewController
to show our app's content. - dispatches events to our views. sendEvent
- handles the keyboard events.
We don't need to add window as a subview to another window. We just create new instance, provide some size and make it visible.
To get the keyboard events, we need to make our new window key. newWindow.makeKey()
. Only one window can be the key at a time.
Output

Check out the source code at github.
Use cases 👨🏻💻
- Commonly we create extra windows for connected screens like TV or Projector. Good examples are Keynote (Presentation Apps) and Games. UIWindow reference document
Most apps need only one window, which displays the app’s content on the device’s main screen. Although we can create additional windows on the device’s main screen, extra windows are commonly used to display content on an external screen, as described in Displaying Content on a Connected Screen.
- One interesting use case come from the iOS developer Gui Rambo did for EmojiPickerUI (macOS-style emoji picker for iPadOS). EmojiPickerUI
Thanks for reading. 🙂