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