做iOS开发的时,很多时候我们需要对获取当前所在的ViewController,搜了一下,大多数答案都不靠谱,都不能正确获取到当前的控制器,不一定能获取到当前的ViewController,于是自己写了一个方法
iOS自带的ViewController有两种
- 一种是普通控制器:UIViewController, UITableViewController, UISearchBarController等
- 一种是容器控制器:
- UINavigationController:
通过childViewController.lastObject获取当前控制器 - UITabBarController
通过selectedViewController 获取当前控制器
- UINavigationController:
页面跳转有push和present,如果有present控制器,则直接取弹出的控制器,如果是导航控制器,则取最后一个,然后一层一层往下取,代码如下:
//方法一: while 循环
func getCurrentVC() -> UIViewController {
//当前windows的根控制器
var vc: UIViewController! = UIApplication.shared.keyWindow?.rootViewController
//通过循环一层一层往下查找
while true {
if vc.presentedViewController != nil {
vc = vc.presentedViewController
}else if vc.isKind(of: UITabBarController.self) {
//如果TabBarController,取当前控制器
vc = (vc as! UITabBarController).selectedViewController
}else if vc.isKind(of: UINavigationController.self) {
//如果是NavigationController,取最后一个控制器(当前)
vc = (vc as! UINavigationController).visibleViewController
}else if vc.childViewControllers.count > 0 {
//如果是普通控制器,找childViewControllers最后一个
vc = vc.childViewControllers.last
}else {
//没有present,没有childViewController,则表示当前控制器
return vc
}
}
}
上面代码只处理了NavigationController和TabBarController,如果你没有修改过NavigationController和TabBarController的默认行为,页面跳转使用默认的push和present,那么是可以正常获取到
//方法二: 递归调用
func getCurrentVC(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController {
if let presented = base?.presentedViewController {
return getCurrentVC(base: presented)
}
if let nav = base as? UINavigationController {
return getCurrentVC(base: nav.visibleViewController)
}
if let tab = base as? UITabBarController {
return getCurrentVC(base: tab.selectedViewController)
}
return base!
}