iOS 获取当前正在显示的ViewController

 

 

 

 

适用范围,tabbar的子视图都是NavigationController,其它情况可以根据情况调整

 

 

- (UIViewController *)getCurrentVC{
    
    UIViewController *result = nil;
    UIWindow * window = [[UIApplication sharedApplication] keyWindow];
    //app默认windowLevel是UIWindowLevelNormal,如果不是,找到UIWindowLevelNormal的
    if (window.windowLevel != UIWindowLevelNormal)
    {
        NSArray *windows = [[UIApplication sharedApplication] windows];
        for(UIWindow * tmpWin in windows)
        {
            if (tmpWin.windowLevel == UIWindowLevelNormal)
            {
                window = tmpWin;
                break;
            }
        }
    }
    id  nextResponder = nil;
    UIViewController *appRootVC=window.rootViewController;
//    如果是present上来的appRootVC.presentedViewController 不为nil
    if (appRootVC.presentedViewController) {
        nextResponder = appRootVC.presentedViewController;
    }else{
        UIView *frontView = [[window subviews] objectAtIndex:0];
        nextResponder = [frontView nextResponder];   <span style="font-family: Arial, Helvetica, sans-serif;">//  这方法下面有详解    </span>
    }
    
    if ([nextResponder isKindOfClass:[UITabBarController class]]){
        UITabBarController * tabbar = (UITabBarController *)nextResponder;
        UINavigationController * nav = (UINavigationController *)tabbar.viewControllers[tabbar.selectedIndex];
//        UINavigationController * nav = tabbar.selectedViewController ; 上下两种写法都行
        result=nav.childViewControllers.lastObject;
        
    }else if ([nextResponder isKindOfClass:[UINavigationController class]]){
        UIViewController * nav = (UIViewController *)nextResponder;
        result = nav.childViewControllers.lastObject;
    }else{
        result = nextResponder;
    }
    
    return result;
}

 

 

 

 

- (nullableUIResponder*)nextResponder  解释

问题1。 如何调用父view的controller里面的方法?

答案如下:
[[self superview ].nextResponder  method];
[[[self superview ] nextResponder]  method];
[self.nextResponder method];
上面的都可以,看情况使用,使用的时候最好判断一下。

官方解释
UIView implements this method by returning the UIViewController object that manages it (if it has one) or its superview (if it doesn’t); UIViewController implements the method by returning its view’s superview; UIWindow returns the application object, and UIApplication returns nil.


问题2:当一个子view需要接收点击事件,而父view也需要接收点击事件, 如何做?

当然, 你可能会说直接调用mysubview.superView即可, 这样做也确实是可以做到,但有时子view是不一定知道有这个特定的父view的存在的,如动态添加子view。

所以这里就可以用到消息响应链拉技术。

下面要做的也就是,让子view接收这些事件后,同时把这些事件继续向上传,会一直传到UIApplication为止。 而在传的过程中,如果子view接收了这些事件,那么事件会自然终止,我们现在可以做的是同时让子view接收事件,而且还让事件不终止,并继续向上传。

摘取一部分说明:

“当用户  与  iPhone的触摸屏  产生  互动时,硬件  就会探测到  物理接触  并且  通知  操作系统。接着  操作系统  就会创建  相应的事件  并且  将  其  传递给  当前正在运行的应用程序的事件队列。然后  这项事件  会被事件循环  传递给  优先响应者物件。优先响应者物件  是  事件  被触发时  和  用户  交互的物件,比如  按钮物件、视图物件。如果  我们  编写了  代码  让  优先响应者  处理  这种类型的事件,那么  它  就会处理  这种类型的事件。处理完  某项事件后,响应者  有  两个选项:1、将  其  丢弃;2、将  其  传递给  响应链条中的下一个响应者。下一个响应者的地址   存储  在当前响应者物件所包含的变量nextResponder当中。如果  优先响应者  无法处理  一项事件,那么  这项事件  就传递给  下一个响应者,直到  这项事件  到达  能处理它的响应者  或者  到达  响应链条的末端,也就是  UIApplication类型的物件。UIApplication类型的物件  收到  一项事件后,也是  要么  处理,要么  丢弃。“

比如  有  一个视图物件,这个视图物件上  有  一个按钮物件。当用户  触摸  这个按钮物件时,作为优先响应者,这个按钮物件  就会收到  一项事件。如果  这个按钮物件  无法处理  这项事件,就会将  这项事件  传递给  视图物件。如果  视图物件  无法处理  这项事件,就会将  这项事件  传递给  视图控制器物件。以此类推。

应该注意的  是  当我们  在使用  响应链条时,一项事件  并不会自动地  从一个响应者  传递到  下一个响应者。如果  要将  一项事件  从一个响应者  传递到  下一个响应者,我们  必须编写  代码  才能办到。”

要做的如下:

子view的代码如下:


- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

{

// 这里可以做子view自己想做的事,做完后,事件继续上传,就可以让其父类,甚至父viewcontroller获取到这个事件了

[[self nextResponder]touchesBegan:toucheswithEvent:event];

}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

{

[[self nextResponder]touchesEnded:toucheswithEvent:event];

}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event

{

[[self nextResponder] touchesCancelled:toucheswithEvent:event];

}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

{

[[self nextResponder] touchesMoved:toucheswithEvent:event];

}

另外需要注意的是:在重写这几个方法时,最好保证这几个方法都重写,否则事件响应链可能会变混乱。这是我的猜测哈,没有实际验证过。


还有一种方法, cocoa在 app 生命周期变化是注册了系统级的通知,我们只需要在viewcontroller中监听一下就行,下面是常用通知的名字  ,   还有很多, 写一个 command 进去看看吧 .

UIKIT_EXTERN NSNotificationName const UIApplicationDidFinishLaunchingNotification;

UIKIT_EXTERN NSNotificationName const UIApplicationDidBecomeActiveNotification;

UIKIT_EXTERN NSNotificationName const UIApplicationWillResignActiveNotification;

UIKIT_EXTERN NSNotificationName const UIApplicationDidReceiveMemoryWarningNotification;

UIKIT_EXTERN NSNotificationName const UIApplicationWillTerminateNotification


这个更加节省代码,而且很好用 .


--------------------- 
作者:想名真难 
来源:CSDN 
原文:https://blog.csdn.net/u014600626/article/details/51455354 
版权声明:本文为博主原创文章,转载请附上博文链接!

另外需要注意的是:在重写这几个方法时,最好保证这几个方法都重写,否则事件响应链可能会变混乱。这是我的猜测哈,没有实际验证过。

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值