user19534819
user19534819

Reputation:

'keywindow' and 'windows' deprecated in IOS 15.0

I'm trying to present the top view controller as the root view controller, the whole code works except that line :

var topController: UIViewController = UIApplication.shared.keyWindow!.rootViewController!

I get the warning :

'keyWindow' was deprecated in iOS 13.0: Should not be used for applications that support multiple scenes as it returns a key window across all connected scenes

Then when I say :

var topController: UIViewController = UIApplication.shared.windows.first { $0.isKeyWindow }!.rootViewController!

I get :

'windows' was deprecated in iOS 15.0: Use UIWindowScene.windows on a relevant window scene instead

And then when I say:

var topController: UIViewController = UIWindowScene.windows.first { $0.isKeyWindow }!.rootViewController!

I get :

Instance member 'windows' cannot be used on type 'UIWindowScene'; did you mean to use a value of this type instead?

Can somebody help me? Sorry if this sounds easy but I'm still a novice. Thanks

Upvotes: 2

Views: 6268

Answers (3)

Brownsoo Han
Brownsoo Han

Reputation: 4711

I make and use some extensions of UIApplication.

func findWindowScenes() -> [UIWindowScene] {
    return Self.shared.connectedScenes.compactMap({ $0 as? UIWindowScene })
}

func findKeyWindow() -> UIWindow? {
    if #available(iOS 15, *) {
        let scenes = findWindowScenes()
        return scenes.first(where: { $0.keyWindow != nil })?.keyWindow ?? scenes.first?.keyWindow
    } else {
        return Self.shared.windows.filter({ $0.isKeyWindow }).first
    }
}

func findKeyRootViewController() -> UIViewController? {
    return findKeyWindow()?.rootViewController
}

Upvotes: 0

Ankur Lahiry
Ankur Lahiry

Reputation: 2315

You can use the following code base

let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow })
extension UIApplication {
    
    class var topViewController: UIViewController? { return getTopViewController() }
    
    private class func getTopViewController(
        base: UIViewController? = UIApplication.keyWindow?.rootViewController) -> UIViewController? {
        if let nav = base as? UINavigationController { return getTopViewController(base: nav.visibleViewController) }
        if let tab = base as? UITabBarController {
            if let selected = tab.selectedViewController { return getTopViewController(base: selected) }
        }
        if let presented = base?.presentedViewController { return getTopViewController(base: presented) }
        return base
    }
}

extension UIApplication {
    static var keyWindow: UIWindow? {
        return shared.windows.first(where: {$0.isKeyWindow})
    }
}

Upvotes: -2

Zeeshan Ahmad II
Zeeshan Ahmad II

Reputation: 1193

you can set/get root view controller as follow:

//        getting the all scenes
        let scenes = UIApplication.shared.connectedScenes
//        getting windowScene from scenes
        let windowScene = scenes.first as? UIWindowScene
//        getting window from windowScene
        let window = windowScene?.windows.first
//        getting the root view controller
        let rootVC = window?.rootViewController
//        changing the root view controller
        window?.rootViewController = someVc

Upvotes: 4

Related Questions