How to get Root view controller in Swift

⋅ 3 min read ⋅ iOS

Table of Contents

In this article, I will show you a quick and dirty way to get a root view controller in an iOS app.

Before iOS 13, you might use the following code to get a key window or a root view controller.

UIApplication.shared.keyWindow?.rootViewController
// Or
UIApplication.shared.windows.first?.rootViewController

But in iOS 13, iOS add is supporting multiple scenes and windows. This makes a concept of a single key window obsolete.

Apple deprecated UIApplication.shared.keyWindow and UIApplication.shared.windows in iOS 13, and iOS 15, respectively.

How to get Root view controller in iOS

So, to get a key window or root view controller in iOS 13 onward, we should use something like this.

extension UIApplication {
var firstKeyWindow: UIWindow? {
// 1
let windowScenes = UIApplication.shared.connectedScenes
.compactMap { $0 as? UIWindowScene }
// 2
let activeScene = windowScenes
.filter { $0.activationState == .foregroundActive }
// 3
let firstActiveScene = activeScene.first
// 4
let keyWindow = firstActiveScene?.keyWindow

return keyWindow
}
}

1 We get all scenes with UIApplication.shared.connectedScenes and compact map them to UIWindowScene, which is the scene that we are interested.
2 Then, we filter only an active scene. Multiple windows support means we can get more than one active scene here.
3 We grab the first scene from array of all active scenes.
4 Then we get a key window from that scene.

Then we can get a root view controller like this.

let vc = UIApplication.shared.firstKeyWindow?.rootViewController

You can easily support sarunw.com by checking out this sponsor.

Sponsor sarunw.com and reach thousands of iOS developers.

Quick and Dirty

I mentioned that this is a quick and dirty implementation because there is a chance that there are two active scenes and we don't really care which one is calling this method.

extension UIApplication {
var firstKeyWindow: UIWindow? {
let windowScenes = UIApplication.shared.connectedScenes
.compactMap { $0 as? UIWindowScene }
// 1
let activeScene = windowScenes
.filter { $0.activationState == .foregroundActive }
// 2
let firstActiveScene = activeScene.first
let keyWindow = firstActiveScene?.keyWindow

return keyWindow
}
}

1 There is a chance that there is more than one active scene.
2 We just randomly picked the first one in this implementation.

As a result, the root view you get might not be the same one that was calling it.

We get a root view controller from the first active scene.
We get a root view controller from the first active scene.

Read more article about iOS or see all available topic

Enjoy the read?

If you enjoy this article, you can subscribe to the weekly newsletter.
Every Friday, you'll get a quick recap of all articles and tips posted on this site. No strings attached. Unsubscribe anytime.

Feel free to follow me on Twitter and ask your questions related to this post. Thanks for reading and see you next time.

If you enjoy my writing, please check out my Patreon https://www.patreon.com/sarunw and become my supporter. Sharing the article is also greatly appreciated.

Become a patron Buy me a coffee Tweet Share
Previous
Different ways to map over Dictionary in Swift

Learn how to map function work with Swift dictionary.

Next
Create Button with Rounded Corner Border in SwiftUI

Learn different ways to create a Button with a Rounded corner Border in SwiftUI.

← Home