skip to Main Content

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

3

Answers


  1. 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
    
    Login or Signup to reply.
  2. 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})
        }
    }
    
    
    Login or Signup to reply.
  3. You can try an alternative solution using the UIResponder class. Climbing up the hierarchy until you reach the first element of the UIWindow type.

        extension UIViewController {
            
            var keyWindow: UIWindow? {
                var parentResponder: UIResponder? = next
                while parentResponder != nil {
                    if parentResponder!.classForCoder is UIWindow.Type {
                        return parentResponder as? UIWindow
                    }
                    parentResponder = parentResponder!.next
                }
                return nil
            }
    
            var rootViewController: UIViewController? {
                keyWindow?.rootViewController
            }
        }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search