我正在使用以下扩展程序来查找最顶层的ViewController。
如果有弹窗出现,上面的代码将会给出
UIAlertController
。
如何获取在UIAlertController
下方的顶部视图控制器?UIAlertController
。
如何获取在UIAlertController
下方的顶部视图控制器?UIApplication.topViewController()
将返回在UIAlertController
下最顶部的UIViewController
extension UIApplication {
class func topViewController(controller: UIViewController? = UIApplication.shared.windows.first?.rootViewController) -> UIViewController? {
if let navigationController = controller as? UINavigationController {
return topViewController(controller: navigationController.visibleViewController)
}
if let tabController = controller as? UITabBarController {
if let selected = tabController.selectedViewController {
return topViewController(controller: selected)
}
}
if let presented = controller?.presentedViewController {
return topViewController(controller: presented)
}
if let alert = controller as? UIAlertController {
if let navigationController = alert.presentingViewController as? UINavigationController {
return navigationController.viewControllers.last
}
return alert.presentingViewController
}
return controller
}
}
extension UIApplication {
class func topViewController(controller: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let navigationController = controller as? UINavigationController {
return topViewController(controller: navigationController.visibleViewController)
}
if let tabController = controller as? UITabBarController {
if let selected = tabController.selectedViewController {
return topViewController(controller: selected)
}
}
if let presented = controller?.presentedViewController {
return topViewController(controller: presented)
}
if let alert = controller as? UIAlertController {
if let navigationController = alert.presentingViewController as? UINavigationController {
return navigationController.viewControllers.last
}
return alert.presentingViewController
}
return controller
}
}
UIAlertController
,如果是,则返回其父级。类似于这样:if let presented = base as? UIAlertController {
return base.presentingViewController
}
extension UIApplication {
class func topViewController(base: UIViewController? = (UIApplication.sharedApplication().delegate as! AppDelegate).window?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return topViewController(base: nav.visibleViewController)
}
if let tab = base as? UITabBarController {
if let selected = tab.selectedViewController {
return topViewController(base: selected)
}
}
if let presented = base?.presentedViewController {
return topViewController(base: presented)
}
if let alert = base as? UIAlertController {
return alert.presentingViewController
}
return base
}
}
if let presented = base?.presentedViewController {
上面了吗? - Jellybase!.presentedViewController
的祖先是 base
。 - Jelly您可以使用 presentingViewController
属性获取 UIAlertController
的父控制器。
extension UIApplication {
class func topViewController(base: UIViewController? = (UIApplication.sharedApplication().delegate as! AppDelegate).window?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return topViewController(base: nav.visibleViewController)
}
if let tab = base as? UITabBarController {
if let selected = tab.selectedViewController {
return topViewController(base: selected)
}
}
if let alert = base as? UIAlertController {
if let presenting = alert.presentingViewController {
return topViewController(base: presenting)
}
}
if let presented = base?.presentedViewController {
return topViewController(base: presented)
}
return base
}
}
在你的代码中使用这些更改,未在XCode上进行测试。
UIAlertController
而不是 UIAlertViewController
。已更新我的回答。 - atulkhatri我认为你想在当前最上面可见的ViewController上推送一个新的VC,而这个VC是UIAlertController,然后这个UIAlertController会立即消失,因为被推送的新VC也被关闭了。最终,你无法推送一个新的VC。
问题在于,如果你新建一个UIAlertView,然后调用show
方法,Cocoa Touch会初始化一个新的窗口,其rootViewController是UIApplicationRotationFollowingController,其presentingViewController是UIAlertController。因此,你无法遍历UIAlertController下面的最高层VC,因为它存在于另一个窗口中!
因此,如果从keyWindow?.rootViewController
遍历topViewController
,找到了一个UIAlertController
,则再次调用topViewController
,但是从你想要的窗口遍历,例如:(UIApplication.sharedApplication().delegate as! AppDelegate).window?.rootViewController
extension UIApplication {
var topViewController: UIViewController? {
var viewController = keyWindow?.rootViewController
guard viewController != nil else { return nil }
var presentedViewController = viewController?.presentedViewController
while presentedViewController != nil, !(presentedViewController is UIAlertController) {
switch presentedViewController {
case let navagationController as UINavigationController:
viewController = navagationController.viewControllers.last
case let tabBarController as UITabBarController:
viewController = tabBarController.selectedViewController
default:
viewController = viewController?.presentedViewController
}
presentedViewController = viewController?.presentedViewController
}
return viewController
}
}
这是正确的:
func firstApplicableViewController() -> UIViewController? {
if (self is UITabBarController) {
let tabBarController = self as? UITabBarController
return tabBarController?.selectedViewController?.firstApplicableViewController()
} else if (self is UINavigationController) {
let navigationController = self as? UINavigationController
return navigationController?.visibleViewController?.firstApplicableViewController()
} else if (self is UIAlertController) {
let presentingViewController: UIViewController = self.presentingViewController!
return presentingViewController.firstApplicableViewController()
} else if self.presentedViewController != nil {
let presentedViewController: UIViewController = self.presentedViewController!
if (presentedViewController is UIAlertController) {
return self
} else {
return presentedViewController.firstApplicableViewController()
}
} else {
return self
}
}