swift 、OC 获取Controller或者View的方法 总结

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

你可能感兴趣的:(swift 、OC 获取Controller或者View的方法 总结)