extension UIViewController { | |
func topMostViewController() -> UIViewController { | |
if self.presentedViewController == nil { | |
return self | |
} | |
if let navigation = self.presentedViewController as? UINavigationController { | |
return navigation.visibleViewController.topMostViewController() | |
} | |
if let tab = self.presentedViewController as? UITabBarController { | |
if let selectedTab = tab.selectedViewController { | |
return selectedTab.topMostViewController() | |
} | |
return tab.topMostViewController() | |
} | |
return self.presentedViewController!.topMostViewController() | |
} | |
} | |
extension UIApplication { | |
func topMostViewController() -> UIViewController? { | |
return self.keyWindow?.rootViewController?.topMostViewController() | |
} | |
} |
Thank you for this gist. Just a small note that visibleViewController is optional so it would be safer to do this:
if let navigation = self.presentedViewController as? UINavigationController {
if let visibleController = navigation.visibleViewController {
return visibleController.topMostViewController()
}
}
above one would not work cause you have to return something, you can use this instead on line 7 :
return navigation.visibleViewController?.topMostViewController() ?? navigation
extension UIViewController {
func topMostViewController() -> UIViewController {
if let presented = self.presentedViewController {
return presented.topMostViewController()
}
if let navigation = self as? UINavigationController {
return navigation.visibleViewController?.topMostViewController() ?? navigation
}
if let tab = self as? UITabBarController {
return tab.selectedViewController?.topMostViewController() ?? tab
}
return self
}
}
This is how to use this code:
let topMostViewController = UIApplication.shared.topMostViewController()
Thanks bud
extension UIViewController { func topMostViewController() -> UIViewController { if let presented = self.presentedViewController { return presented.topMostViewController() } if let navigation = self as? UINavigationController { return navigation.visibleViewController?.topMostViewController() ?? navigation } if let tab = self as? UITabBarController { return tab.selectedViewController?.topMostViewController() ?? tab } return self } }
@bartleby Thank you sir.
i think need to add for pageviewcontroller related code
I'm curious where viewController's children has gone?
Since self.keywindow is deprecated in iOS 13.0, I changed extension like this.
extension UIApplication {
func topMostViewController() -> UIViewController? {
return UIApplication.shared.windows.filter { $0.isKeyWindow }.first?.rootViewController?.topMostViewController()
}
}
thanks!
'windows' was deprecated in iOS 15.0, updated extension:
func topMostViewController() -> UIViewController? {
let vc = UIApplication.shared.connectedScenes.filter {
$0.activationState == .foregroundActive
}.first(where: { $0 is UIWindowScene })
.flatMap( { $0 as? UIWindowScene })?.windows
.first(where: \.isKeyWindow)?
.rootViewController?
.topMostViewController()
return vc
}
extension UIViewController {
func topMostViewController() -> UIViewController {
if self.presentedViewController == nil {
return self
}
if let navigation = self.presentedViewController as? UINavigationController {
return navigation.visibleViewController!.topMostViewController()
}
if let tab = self.presentedViewController as? UITabBarController {
if let selectedTab = tab.selectedViewController {
return selectedTab.topMostViewController()
}
return tab.topMostViewController()
}
return self.presentedViewController!.topMostViewController()
}
}
Tested with ios 15.4.1
@available(iOS 15.0, *)
var keyWindow:UIWindow? {
let scene = UIApplication.shared.connectedScenes.filter({$0.activationState == .foregroundActive}).first as? UIWindowScene
let keyWindow = scene?.keyWindow
return keyWindow
}
@ielyas please, your code work with iPhone fine, but on iPad it returns vc : Fatal error: Unexpectedly found nil while unwrapping an Optional value
Any idea what's different for the iPad?
Thank you! Just a note if anyone else uses this. If your root view is either a tab or navigation view as it was in my case this will not work.
I added this code above
if self.presentedViewController == nil {