百度中有一大把获取当前UIViewController的代码,但是在ios8一旦present之后就拿不到了,在百度找了一大推都是没用的东西,后来翻墙找老外,有老外发现了这个问题,但是给出的解决方案也不尽人意,最后笔者在实际解决中一次偶然机会发现了这个问题。

首先是ios7下面的代码:
//获取当前屏幕显示的viewcontroller
- (UIViewController *)getCurrentVC
{  UIViewController *result = nil;  UIWindow * window = [[UIApplication sharedApplication] keyWindow];  if (window.windowLevel != UIWindowLevelNormal)  {  NSArray *windows = [[UIApplication sharedApplication] windows];  for(UIWindow * tmpWin in windows)  {  if (tmpWin.windowLevel == UIWindowLevelNormal)  {  window = tmpWin;  break;  }  }  }  UIView *frontView = [[window subviews] objectAtIndex:0];  id nextResponder = [frontView nextResponder];  if ([nextResponder isKindOfClass:[UIViewController class]])  result = nextResponder;  else  result = window.rootViewController;  return result;
}  

IOS8下面获取当前VC代码如下(兼容ios7):

+(UIViewController*)getCurrentKeyController
{UIViewController *result;UIWindow *topWindow = [[[UIApplication sharedApplication] delegate] window];NSLog(@"%@",[[UIApplication sharedApplication] windows]);if (topWindow.windowLevel != UIWindowLevelNormal){NSArray *windows = [[UIApplication sharedApplication] windows];for(topWindow in windows){if (topWindow.windowLevel == UIWindowLevelNormal)break;}}id lenderClass = objc_getClass("UILayoutContainerView"); // 通过字符串名字,获取类id nextResponder;UIView *rootView = [[topWindow subviews] objectAtIndex:0];if(IsIOS8&&![rootView isMemberOfClass:[lenderClass class]]){NSArray *arr = [rootView valueForKey:@"subviewCache"];if(arr.count>0){UIView *v = [arr objectAtIndex:0];nextResponder = [v nextResponder];}else{nextResponder = [[[rootView subviews] objectAtIndex:0] nextResponder];}}else{nextResponder = [rootView nextResponder];}if ([nextResponder isKindOfClass:[UIViewController class]]){result = nextResponder;}else if ([topWindow respondsToSelector:@selector(rootViewController)] && topWindow.rootViewController != nil){result = topWindow.rootViewController;}else{NSAssert(NO, @"ShareKit: Could not find a root view controller.  You can assign one manually by calling [[SHK currentHelper] setRootViewController:YOURROOTVIEWCONTROLLER].");}return result;
}

比起直接分享代码,笔者更愿意跟大家分享我解决这个问题的过程和思路

  1. ios7下面 window 的subview最上面一层一定是UILayoutContainerView 这可以让我捕获到viewcontroller ios8下面是一个过度的UITransitionView 捕获不到VC
    这里面比较复杂 我那天搞了一个下午 我猜测苹果的用意应该是不允许今后随意捕捉用户界面 给用户一个干净的体验环境。

  2. UILayoutContainerView(容器view)这个在api只有class 看不到任何接口~ UITransitionView(过度view)这个连api都进不去。

  3. 在IOS7下UIApplication的Window的subView的第一个view一定是UILayoutContainerView,而它的nextResponder就是一个ViewController,这是为什么能给通过Window找到ViewController的原因。在ios8中,一旦使用了presentViewController,而presentViewController的UIApplication的Window的subView的第一个view就变成了UITransitionView,它的nextResponder还是一个Window,这样看起来似乎有一种Window与UITransitionView循环的情况,笔者也不清楚苹果是怎么做到的。
  4. 后来我发现,在IOS8之下,其实Window的UILayoutContainerView被偷偷藏在了Window的subView的第一个view的一个叫做subviewCache的数组里面,于是我利用Runtime获取了这个subviewCache数组里面的UILayoutContainerView,问题就解决了。这就是上面一段代码
`id lenderClass = objc_getClass("UILayoutContainerView"); // 通过字符串名字,获取类id nextResponder;UIView *rootView = [[topWindow subviews] objectAtIndex:0];if(IsIOS8&&![rootView isMemberOfClass:[lenderClass class]]){NSArray *arr = [rootView valueForKey:@"subviewCache"];if(arr.count>0){UIView *v = [arr objectAtIndex:0];nextResponder = [v nextResponder];}else{nextResponder = [[[rootView subviews] objectAtIndex:0] nextResponder];}}

加了一个判断的原因。


[欢迎读者指出不足之处,转载请注明出处。]

IOS8如何获取当前UIViewController相关推荐

  1. 【IOS】获取顶层UIViewController

    2019独角兽企业重金招聘Python工程师标准>>> Objective-c版本: - (UIViewController *)appRootViewController {UIV ...

  2. 地图篇-01.获取用户位置

    地图篇-01.获取用户位置 今天把地图整理了一下,共享出来和大家一起分享,希望帮助到不了解的朋友,当然很精通的朋友希望指正小生的不足. 1.说到地图,首先要接触一个framework -CoreLoc ...

  3. iOS7不越狱获取IMEI

    原创文章不易,转载时请保留原始链接:http://blog.csdn.net/ookcode/article/details/41865477   谢谢!! 大概在iOS SDK 3.2的时候,我们可 ...

  4. 谈iphone电话短信增强工具kuaidail软件的实现

    首先声明,本人不是kuaidail软件的实现作者,是在做相关的项目过程中,想到了也实现了类似的功能,kuaidail软件本身并 没有公布相关实现细节,所以在此分享一下. 在这里,可以了解kuaidai ...

  5. IOS ReplayKit RPScreenRecorder 的屏幕录制功能

    IOS ReplayKit RPScreenRecorder 的屏幕录制功能 开始录制有两个方法: (void)startRecordingWithMicrophoneEnabled:(BOOL)mi ...

  6. 如何知道页面浏览时长?

    1. 前言 页面浏览时长是用于统计用户在页面的停留时长.对于神策分析 iOS SDK 而言,在没有推出页面浏览时长自动采集功能之前,客户是通过手动调用开始计时和结束计时的相关接口实现页面浏览时长采集的 ...

  7. iOS 获取当前的UIViewController

    //获取当前屏幕显示的viewcontroller +(UIViewController *)getCurrentWindowVC { UIViewController *result = nil; ...

  8. iOS8 获取通知设置状态

    UIUserNotificationSettings *settings = [[UIApplication sharedApplication] currentUserNotificationSet ...

  9. UIVIewController自定义切换效果-b

    之前介绍动画时提过UIView的转场动画,但是开发中我们碰到更多的viewController的切换,ios中常见的viewcontroller切换有四种:模态视图,导航栏控制器,UITabBarCo ...

最新文章

  1. ASP.NET C# 生成静态页面简单方法
  2. vc c语言坐标图,VC++6.0下C语言画图编程问题
  3. Python 内置模块之 re
  4. 基于react antd的新的tag和Badge的组合使用
  5. flash动画制作成品_Flash如何制作雪糕被吃掉的动画
  6. 如何更换tomcat版本
  7. BP神经网络 MATLAB源程序
  8. eclipse 导入项目后,在工程图标上出现红叉,但是工程中的文件并没有提示错误的解决方法
  9. HC-SR04 超声波原理图讲解与时序分析与arduino使用
  10. 什么软件测试固态硬盘坏没坏,固态硬盘容易坏吗 SSD固态硬盘坏掉前有什么征兆【详细介绍】...
  11. 硬盘坏了,如何检测与修复。
  12. Python实现鸡群算法
  13. 基于pyqt5的登录界面及人脸识别功能界面相互跳转的设计(1)
  14. 人大金仓命令行客户端工具KSQL系列1
  15. 【第004篇】Java工具类之货币大小写转换
  16. qca9535 tftp32 刷机_20151210编译高通的qca9531的wireless版本 修改版本4
  17. 果园机器人作文开头_果园机器人300字作文4篇
  18. 从保障淘宝到全球市场“第一阵营”,阿里云的DDoS防护之路走了多远?
  19. 作为程序员的你,常用的工具软件有哪些?
  20. 电脑和树莓派之间传输文件

热门文章

  1. rabbitmq java教程_GitHub - maxwellyue/rabbitmq-tutorial-java: RabbitMQ官方教程的翻译和说明--Java版...
  2. java中注解的解析_【Java】中的注解与注解解析器
  3. 【数据分析R语言系列】R和RStudio的下载和安装, R在 Ubuntu 和CentOS 系统下的安装
  4. 二十、App爬虫环境搭建并测试监听微信
  5. CIKM 2021 | Deep Retrieval:字节跳动深度召回模型论文精读
  6. UC伯克利摘最佳论文、Hugging Face获最佳demo,EMNLP 2020奖项公布
  7. 从Grid R-CNN到Grid R-CNN Plus:基于网格的目标检测演化
  8. nn.Sequential(*modules)
  9. vue中页面跳转传值_vue的页面跳转方式和传值、取值
  10. IntelliJ IDEA快捷键学习