UIAlertController下最顶级的ViewController

时间:2016-03-29 12:36:19

标签: ios swift uiviewcontroller uialertcontroller

我使用以下扩展名来查找top most ViewController。 如果出现提醒,则上面的代码会显示UIAlertController。 如何在 UIAlertController下获得顶视图控制器

6 个答案:

答案 0 :(得分:2)

创建如下所示的UIApplication扩展,UIApplication.topViewController()将返回UIViewController下最上面的UIAlertController

iOS 13 +

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
    }

}

iOS 12-

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
    }

}

答案 1 :(得分:1)

您可以使用UIAlertController属性

获取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 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上进行测试。

答案 2 :(得分:0)

您可以检查下一个viewController是否为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
   }
}

答案 3 :(得分:0)

我使用此扩展来获取UIAlertController下的最顶层视图控制器,基本上我做的是当我找到一个UIAlertController时停止寻找顶视图控制器。

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
}

}

答案 4 :(得分:0)

我认为你想在当前顶级可见VC上推出一个新的VC,这是一个UIAlertController,然后这个UIAlertController会立即消失,导致新的VC被解雇。最后,你无法推动新的VC。

问题是,如果您新建一个UIAlertView,然后调用show,Cocoa Touch将初始化一个新窗口,其中rootViewController是UIApplicationRotationFollowingController,其presentationViewController是UIAlertController。所以你不能遍历UIAlertController下最顶层的VC,因为它存在于另一个窗口中!

因此,如果topViewController遍历keyWindow?.rootViewController,请找到UIAlertController,再次致电topViewController,但要从window遍历您想要的内容,例如{{1} }}

答案 5 :(得分:0)

这是正确的:

    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
        }
    }