iOS响应事件传递, nextResponder研究

Posted 黄建军的技术博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS响应事件传递, 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.

即如下代码可以进行判断:

id next = [self nextResponder];
while(![next isKindOfClass:[ViewController class]])//这里跳不出来。。。有人说这里跳不出来,其实是因为它没有当前这个view放入ViewController中,自然也就跳不出来了,会死循环,使用时需要注意。
{
next = [next nextResponder];
}
if ([next isKindOfClass:[ViewController class]])
{
controller = (ViewController *)next;
}


问题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获取到这个事件了

[[selfnextResponder]touchesBegan:toucheswithEvent:event];

}

 

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

{

[[selfnextResponder]touchesEnded:toucheswithEvent:event];

}

 

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

{

[[selfnextResponder] touchesCancelled:toucheswithEvent:event];

}

 

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

{

[[selfnextResponder] touchesMoved:toucheswithEvent:event];

}

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















以上是关于iOS响应事件传递, nextResponder研究的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Swift 中将触摸事件发送到 nextResponder

事件传递和响应机制

iOS开发 - 事件传递响应链

iOS开发 - 事件传递响应链

iOS-事件传递和响应机制

iOS中的事件传递和响应者链条