本文主要是介绍IOS8如何获取当前UIViewController,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
百度中有一大把获取当前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;
}
比起直接分享代码,笔者更愿意跟大家分享我解决这个问题的过程和思路
ios7下面 window 的subview最上面一层一定是UILayoutContainerView 这可以让我捕获到viewcontroller ios8下面是一个过度的UITransitionView 捕获不到VC
这里面比较复杂 我那天搞了一个下午 我猜测苹果的用意应该是不允许今后随意捕捉用户界面 给用户一个干净的体验环境。UILayoutContainerView(容器view)这个在api只有class 看不到任何接口~ UITransitionView(过度view)这个连api都进不去。
- 在IOS7下UIApplication的Window的subView的第一个view一定是UILayoutContainerView,而它的nextResponder就是一个ViewController,这是为什么能给通过Window找到ViewController的原因。在ios8中,一旦使用了presentViewController,而presentViewController的UIApplication的Window的subView的第一个view就变成了UITransitionView,它的nextResponder还是一个Window,这样看起来似乎有一种Window与UITransitionView循环的情况,笔者也不清楚苹果是怎么做到的。
- 后来我发现,在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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!