1、获取UIViewController
场景1:
在项目中,我们经常需要获取当前所看到的View Controller,比如从其他App跳回我们的App中时,获取当前View Controller:
extension UIViewController {
class func currentViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return currentViewController(base: nav.visibleViewController)
}
if let tab = base as? UITabBarController {
return currentViewController(base: tab.selectedViewController)
}
if let presented = base?.presentedViewController {
return currentViewController(base: presented)
}
return base
}
}
用法:
let theViewControllerYouSee = UIViewController.currentViewController()
场景2:如MVVM模式中使用
当前view中获取UIViewController
方法一: 通过响应者链获取
// 获取view当前所在的UIViewController
func getCurrentViewController() -> UIViewController {
// 1.通过响应者链关系,取得此时图的下一个响应者
var nextResp: UIResponder?
nextResp = self.next!
repeat {
// 2.判断响应者对象是否是视图控制器类型
if ((nextResp as? UIViewController) != nil) {
return nextResp as! UIViewController
}
else{
nextResp = next?.next
}
} while nextResp != nil
return UIViewController()
}
上面的方法是根据下面的OC方法改写的
- (UIViewController *) getCurrentViewController {
UIResponder *next = [self nextResponder];
do {
if ([next isKindOfClass:[UIViewController class]]) {
return (UIViewController *)next;
}
next = [next nextResponder];
} while (next != nil);
return nil;
}
方法二: 通过当前UIView的superView遍历获取
1)UIView实例化调用
func getCurrentViewController() -> UIViewController? {
// 1.通过响应者链关系,取得此时图的下一个响应者
var next: UIView? = self
repeat {
// 2.判断响应者对象是否是视图控制器类型
if let nextResp = self.next , nextResp.isKind(of: UIViewController.self) {
return (nextResp as! UIViewController)
}
next = next?.superview
} while next != nil
return nil
}
2) UIView 静态调用
static func currentViewController(view: UIView)-> UIViewController? {
var next:UIView? = view
repeat{
if let nextResponder = next?.next,
nextResponder.isKind(of: UIViewController.self) {
return (nextResponder as! UIViewController)
}
next = next?.superview
}while next != nil
return nil
}
注意:1)和 2)方法可在控制器中调用,但 方法一 和 1)方法 在自定义UIView中
调用无反应,2)方法则可以,具体原因还有待研究,也希望知道的朋友告知。
场景3:获取window中当前页面的最顶层控制器
//获取当前页面的最顶层控制器
func currentVc() -> UIViewController {
let keywindow = UIApplication.shared.keyWindow
let firstView: UIView = (keywindow?.subviews.first)!
let secondView: UIView = firstView.subviews.first!
let vc = viewForController(view: secondView)
return vc!
}
func viewForController(view:UIView)->UIViewController?{
var next:UIView? = view
repeat{
if let nextResponder = next?.next, nextResponder is UIViewController {
return (nextResponder as! UIViewController)
}
next = next?.superview
}while next != nil
return nil
}
调用方法:
let vc = self.currentVc()//获取当前屏幕中顶层控制器
if vc.childViewControllers.first is ManagerRootViewController {
self.perform(#selector(ManagerRootViewController.disAction), on: Thread.main, with: nil, waitUntilDone: true)
}
//如果是UINavgitionController,那么其first就是rootViewController
perform使用方法:
在A控制器想让B控制器调用B中xx的方法,perform的用法
onThread:执行xx方法的线程
waitUntilDone:true代表先执行xx方法再执行一下代码.
文章仅供参考,有不完善的地方,望朋友们相告知
文章参考:
https://www.jianshu.com/p/66ecd88b4210
https://www.jianshu.com/p/30b341d5edfa
网友评论