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;
}

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

  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];
        }

    }

加了一个判断的原因。


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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值