查看: 5079|回复: 0

[IOS开发教程] iOS学习——获取当前最顶层的ViewController

发表于 2018-2-19 08:00:04

  在ios开发过程中,我们经常性会需要获取当前页面的ViewController,然后利用ViewController进行一些操作,例如在最顶层的ViewController上展示一个UIAlertController,或者在最顶层的ViewController上present另一个ViewController,或者进行其他操作。

1 实现思路

  通过最底层的ViewController依次向上寻找,直到找到最顶层的ViewController,也就是从UIApplication的keyWindow的rootViewController开始寻找(如果有多个UIWindow则要考虑UIWindow的选择问题。

  在寻找的过程中,要分别考虑当前ViewController是UITabBarController和UINavigationController的情况,同时还要考虑到当前ViewController是否通过 presentViewController:animated:completion: 模态展示了其他ViewController。

2 实现方法 方法一:
  1. - (UIViewController *)topViewController {
  2. UIViewController *resultVC;
  3. resultVC = [self _topViewController:[[UIApplication sharedApplication].keyWindow rootViewController]];
  4. while (resultVC.presentedViewController) {
  5. resultVC = [self _topViewController:resultVC.presentedViewController];
  6. }
  7. return resultVC;
  8. }
  9. - (UIViewController *)_topViewController:(UIViewController *)vc {
  10. if ([vc isKindOfClass:[UINavigationController class]]) {
  11. return [self _topViewController:[(UINavigationController *)vc topViewController]];
  12. } else if ([vc isKindOfClass:[UITabBarController class]]) {
  13. return [self _topViewController:[(UITabBarController *)vc selectedViewController]];
  14. } else {
  15. return vc;
  16. }
  17. return nil;
  18. }
复制代码

使用方法:

  1. UIViewController *topmostVC = [self topViewController];
复制代码
方法二:
  1. //获取当前屏幕显示的viewcontroller
  2. - (UIViewController *)getCurrentVC
  3. {
  4. UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
  5. UIViewController *currentVC = [self getCurrentVCFrom:rootViewController];
  6. return currentVC;
  7. }
  8. - (UIViewController *)getCurrentVCFrom:(UIViewController *)rootVC
  9. {
  10. UIViewController *currentVC;
  11. if ([rootVC presentedViewController]) {
  12. // 视图是被presented出来的
  13. rootVC = [rootVC presentedViewController];
  14. }
  15. if ([rootVC isKindOfClass:[UITabBarController class]]) {
  16. // 根视图为UITabBarController
  17. currentVC = [self getCurrentVCFrom:[(UITabBarController *)rootVC selectedViewController]];
  18. } else if ([rootVC isKindOfClass:[UINavigationController class]]){
  19. // 根视图为UINavigationController
  20. currentVC = [self getCurrentVCFrom:[(UINavigationController *)rootVC visibleViewController]];
  21. } else {
  22. // 根视图为非导航类
  23. currentVC = rootVC;
  24. }
  25. return currentVC;
  26. }
复制代码
  解析代码主要使用了递归的思想(哈哈哈,毕业工作半年,发觉第一次写iOS用到递归,突然觉得高大上)。
[UIApplication sharedApplication].keyWindow.rootViewController获取到的是项目的根视图,结合可能用到UITabBarController或者UINavigationController作为导航结构,以及可能present出新的VC,其实如果用storyboard的方式写UI的话就很清晰,类似树的结构,再利用递归找到当前视图。   ps:     如果是需要push新的视图,就非常简单了。用上面的方法获取到顶层的视图,判断currentVC.navigationController是否为nil。(为nil,则新建UINavigationController,然后再push;否则直接用currentVC.navigationController去push)。 三 扩展

  如果用到的场景主要是vc里,可以弄成类别如下:

  1. #import "UIViewController+Helper.h"
  2. @property (nonatomic, strong ,readonly) UIViewController * _Nullable currentVC;
  3. //当前屏幕显示的viewcontroller
  4. -(UIViewController *)currentVC{
  5. UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
  6. UIViewController *controller = [self getCurrentVCFrom:rootViewController];
  7. return controller;
  8. }
  9. //getCurrentVCFrom参考上文两种方法
复制代码



回复

使用道具 举报