事件的完整处理过程
1.先将事件对象由上到下传递(由父控件传递给子控件),找到最合适的控件来处理这个事件
2.调用合适控件的touches...方法
3.如果调用了(super touches …)就会将事件顺着响应链条往上传递,传递给上一个响应者
4.接着就会调用上一个响应者的 touches…方法
1.响应者链条是由多个响应者对象连接起来的链条,(响应者:能处理事件的对象)
2.利用响应者链条,能让多个控件处理同一个触摸事件
3.怎么利用响应者链条?谁是上一个响应者
上一个响应者:
1.如果当前的view是控制器的view,那么控制器是上一个响应者
2.如果当前的view不是控制器view,那么view的父控件是上一个响应者
响应者对象
在iOS中不是任何对象都能处理事件,只有继承了UIResponder的对象才能接受并处理事件,我们称之为“响应者对象”。例如常见的 :UIApplication UIViewController UIView
UIResponder 可以处理触摸事件、按压事件(3D touch)、远程控制事件、硬件运动事件。
事件的传递
1. 发生触摸事件后,系统会将该事件加入到一个由UIApplication 管理的事件队列中。因为队列的特点是FIFO,即先进先出,先产生的事件先处理(首先接收到事件的是UIApplication)。
2. UIApplication 会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常先发送事件给应用程序的主窗口(keyWindow)。
3. 主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件。找到合适的视图控件后,就会调用视图控件的touches方法来作具体的事件处理。
触摸事件的传递是从父控件传递到子控件: UIApplication->window->寻找处理事件最合适的view
UIView不能接收触摸事件的 4 种情况:
1. 不允许交互 :userInteractionEnabled = NO,当前视图不可交互,该视图上面的子视图也不可与用户交互。用户触发的事件都会被该视图忽略(其他视图照常响应),并且该视图对象也会从事件响应队列中被移除。
2. 隐藏 :如果把父控件隐藏,那么子控件也会隐藏,隐藏的控件不能接收事件
3. 透明度 :如果设置一个控件的透明度<0.01,会直接影响子控件的透明度。alpha:0.0~0.01为透明。
4. 子视图的部分区域超过父视图,也不会接收触摸事件,因为父视图在调用 pointInside方法时会返回NO。说明触摸点不在自己范围内,则当前 view 的hitTest: withEvent:方法返回 nil,当前 view上 的所有 subview 都不做判断。
注意:如果 Touch 位置超过视图边界,hitTest:withEvent 方法将忽略这个视图和它的所有子视图。结果就是,当视图的ciipsToBounds属性为NO,子视图超过视图边界也不会接收到事件 ,即使 触摸点在它上面。
不管视图能不能处理事件,只要点击了视图就都会产生事件,关键在于该事件最终是由谁来处理。 系统通过 hitTest:(CGPoint)point withEvent:(UIEvent*)even 找到最适合处理该事件的view。
应用如何找到最合适的控件来处理事件
1. 首先判断主窗口(keyWindow)自己是否能接受触摸事件 hitTest 方法。
2. 判断触摸点是否在自己身上,通过pointInside 方法来判断。
3. 如果上面 2 步都满足条件,会把这个事件交给 view处理,会对 view的 subviews子控件数据 进行遍历,直至没有更合适的view为止。
注意:采取从数组最后面往前遍历子控件的方式,因为后添加的view在最上面,最上层的响应者能最先接受响应,阻断事件继续传递,从而降低遍历循环次数。
5. 如果没有符合条件的子控件,那么就认为自己最合适处理这个事件,return self 。
寻找最合适的view底层剖析 两个重要的方法:
piontinside方法使用场景 : IOS 增加按钮点击区域 - 使按钮的点击反应区域变大
-(UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event 什么时候调用
事件传递给谁,就会调用谁的hitTest:withEvent:方法。
作用
寻找并返回能够响应事件, 最合适的view,不管点击哪里,最合适的view都是 hitTest 方法中返回的那个view。
注 意:不管这个控件能不能处理事件,也不管触摸点在不在这个控件上,事件都会先传递给这个控件,通过调用 hitTest 方法来判断是否可以处理事件。
拦截事件的处理
通过重写 hitTest 方法,返回指定的view 。就可以拦截事件的传递过程,想让谁处理事件谁就处理事件。
注 意:如果 hitTest 方法中返回 nil,那么调用该方法的控件本身和其子控件都不是最合适的view,也就是在自己身上没有找到更合适的view。如果同一层级的其他控件也没有合适的view,那么最合适的 view 就是父控件。
不管子控件是不是最合适的view,系统默认都要先把事件传递给子控件,子控件调用自己的hitTest:withEvent: 方法后才知道有没有更合适的view。即便父控件是最合适的view了,子控件的hitTest:withEvent:方法还是会调用。
技巧: 想让谁成为最合适的view 就重写谁父控件的hitTest:withEvent:方法返回指定的子控件,或者重写自己的hitTest:withEvent:方法 return self。但是, 建议在父控件的hitTest:withEvent:中返回子控件作为最合适的view
原因呢:当遍历子控件时,如果触摸点不在子控件A自己身上而是在子控件B身上,想要返回子控件A作为最合适的view,采用返回自己的方法可能会导致还没有来得及遍历A自己,就有可能已经遍历了点真正所在的view B。这就导致了返回的不是自己而是触摸点真正所在的view。所以建议在父控件的hitTest:withEvent:中返回子控件作为最合适的view。
找到最合适的view 后,就会调用该view的 touches 方法处理具体的事件。
触摸事件由触屏生成后如何传递到当前应用?
系统响应阶段
用户触摸屏幕,系统硬件进程会获取到这个点击事件,将事件简单处理封装后存到系统中,由于硬件检测进程和当前App进程是两个进程,所以进程两者之间传递事件用的是端口通信。
1. 指触碰屏幕,屏幕感应到触碰后,将事件交由IOKit处理。
2. IOKit 将触摸事件封装成一个IOHIDEvent 对象,并通过mach port传递给SpringBoad进程。mach port 进程端口,各进程之间通过它进行通信。
3. SpringBoad 是一个系统进程,统一管理和分发系统接收到的触摸事件。将触摸事件交给前台app进程来处理。
参考: RunLoop原理学习 -
APP响应阶段
1. APP进程的mach port 接收到 SpringBoard 进程传递来的触摸事件,主线程的 runloop被唤醒,触发了source1回调。
2. source1回调又触发了一个source0回调,将接收到的 IOHIDEvent 对象封装成 UIEvent 对象。
3. source0 回调内部将触摸事件添加到 UIApplication 对象的事件队列中。事件出队后,UIApplication开始寻找最佳响应者,这个过程又称hit-testing。
3. 系统判断本次触摸是否导致了一个新的事件。如果是,系统会先从响应网中寻找响应链。如果不是,说明该事件是当前正在进行中的事件产生的一个Touch message, 也就是说已经有保存好的响应链
4. 寻找到最佳响应者后,事件就在响应链中的传递及响应了。
响应者链条:由多个响应者对象连接起来的链条
在iOS程序中无论是最后面的UIWindow还是最前面的某个按钮,它们的摆放是有前后关系的,一个控件可以放到另一个控件上面或下面,那么用户点击某个控件时是触发上面的控件还是下面的控件呢,这种先后关系构成一个链条就叫“响应者链”。
事件在 响应者 链上传递,最终结果是事件被处理或被抛弃。响应者链条能很清楚的看见每个响应者之间的联系,并且可以让一个事件多个对象处理。
每一个响应者对象(UIResponder对象)都有一个nextResponder方法,用于获取响应链中当前对象的下一个响应者。因此,一旦事件的第一响应者确定了,这个事件所处的响应链就确定了。
响应者对象默认的 nextResponder 如下:
1. UIView 的 nextResponder 属性,如果有管理此 view 的 UIViewController 对象,则为此 2. UIViewController 对象;否则 nextResponder 即为其 superview。
3. UIViewController 的 nextResponder 属性为其管理 view 的 superview.
若 VC 是window的根视图rootVC,则其 nextResponder 为 UIWindow ;
若 VC 是从别的控制器present出来的,则其nextResponder为presenting view controller。
4. UIWindow 的 nextResponder 属性为 UIApplication 对象。
5. UIApplication 的 nextResponder 属性为 nil。
若当前应用的app delegate是一个UIResponder对象,且不是UIView、UIViewController或app本身,则UIApplication的nextResponder为app delegate。
响应者链的事件传递过程:
1. 如果当前view是控制器的view,那么控制器就是上一个响应者,事件就传递给控制器;如果当前view不是控制器的view,那么父视图就是当前view的上一个响应者,事件就传递给它的父视图
2. 在视图层次结构的最顶级视图,如果也不能处理收到的事件或消息,则其将事件或消息传递给window对象进行处理
3. 如果window对象也不处理,则其将事件或消息传递给UIApplication对象
4. 如果UIApplication也不能处理该事件或消息,则将其丢弃
响应者对于接收到的事件有3种操作:
1. 不拦截,默认操作. 事件会自动沿着默认的响应链向上传递,(touch方法默认不处理事件,只传递事件),将事件交给上一个响应者进行处理.
UIResponder中的默认实现是什么都不做,但UIKit中UIResponder的直接子类(UIView,UIViewController…) 的默认实现是将事件沿着responder chain继续向上传递到下一个responder, 即nextResponder。
2. 拦截,不再往下分发事件, 重写 touchesBegan:withEvent:进行事件处理,不调用父类的 touchesBegan:withEvent, 事件到这里就结束传递进行处理。
3. 拦截,继续往下分发事件, 重写自己的 touchesBegan:withEvent: 进行事件处理,同时调用 [super touchesBegan:withEvent:] 将事件往下传递,达到 一个事件多个对象处理 的目的。
建议使用:[super touchesBegan:touches withEvent:event]
super 的touches对应方法中默认将事件继续向上传递给 next responder。
不建议直接向nextResponder发送消息,这样可能会漏掉父类对这一事件的其他处理。
[self.nextResponder touchesBegan:touches withEvent:event]
手势事件会打断响应链的传递。因为手势比响应链拥有更高的优先级,添加了手势的View 会阻止子View响应链,手势会最先响应,并对事件进行处理。此事件不再响应链中向上传递。
_UIApplicationHandleEventQueue() 识别了一个手势时,首先调用 Cancel 将当前的 touchesBegin/Move/End 系列回调打断。随后系统将对应的 UIGestureRecognizer 标记为待处理。
苹果注册了一个 Observer 监测 BeforeWaiting (Loop即将进入休眠) 事件,这个Observer的回调函数是 _UIGestureRecognizerUpdateObserver(),其内部会获取所有刚被标记为待处理的 GestureRecognizer,并执行GestureRecognizer的回调。当UIGestureRecognizer 变化(创建/销毁/状态改变)时,回调都会进行处理。
事件的传递和响应的区别:
事件的传递是从上到下(父控件到子控件),事件的响应是从下到上(顺着响应者链条向上传递:子控件到父控件。
可根据一个view 找到它对应的VC控制:
参考文章:
史上最详细的iOS之事件的传递和响应机制-原理篇 -
iOS 响应者及响应者链 -
iOS - 为什么要在主线程中操作UI -
注 意 : 如果父控件不能接受触摸事件,那么子控件就不可能接收到触摸事件
UIView不能接收触摸事件的三种情况:
注 意 :默认UIImageView不能接受触摸事件,因为不允许交互,即userInteractionEnabled = NO。所以如果希望UIImageView可以交互,需要设置UIImageView的userInteractionEnabled = YES。
1.点击一个UIView或产生一个触摸事件A,这个触摸事件A会被添加到由UIApplication管理的事件队列中(即,首先接收到事件的是UIApplication)。
2.UIApplication会从事件对列中取出最前面的事件(此处假设为触摸事件A),把事件A传递给应用程序的主窗口(keyWindow)。
3.窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件。(至此,第一步已完成)
如果想让某个view不能处理事件(或者说,事件传递到某个view那里就断了),那么可以通过刚才提到的三种方式。比如,设置其userInteractionEnabled = NO那么传递下来的事件就会由该view的父控件处理。
例如,不想让蓝色的view接收事件,那么可以设置蓝色的view的userInteractionEnabled = NO那么点击黄色的view或者蓝色的view所产生的事件,最终会由橙色的view处理,橙色的view就会成为最合适的view。
所以,不管视图能不能处理事件,只要点击了视图就都会产生事件,关键在于该事件最终是由谁来处理!也就是说,如果蓝色视图不能处理事件,点击蓝色视图产生的触摸事件不会由被点击的视图(蓝色视图)处理!
注意:如果设置父控件的透明度或者hidden,会直接影响到子控件的透明度和hidden。如果父控件的透明度为0或者hidden = YES,那么子控件也是不可见的!
应用如何找到最合适的控件来处理事件?
1.首先判断主窗口(keyWindow)自己是否能接受触摸事件
2.触摸点是否在自己身上
3.从后往前遍历子控件,重复前面的两个步骤(首先查找数组中最后一个元素)
4.如果没有符合条件的子控件,那么就认为自己最合适处理
详述:1.主窗口接收到应用程序传递过来的事件后,首先判断自己能否接手触摸事件。如果能,那么在判断触摸点在不在窗口自己身上
2.如果触摸点也在窗口身上,那么窗口会从后往前遍历自己的子控件(遍历自己的子控件只是为了寻找出来最合适的view)
3.遍历到每一个子控件后,又会重复上面的两个步骤(传递事件给子控件,1.判断子控件能否接受事件,2.点在不在子控件上)
4.如此循环遍历子控件,直到找到最合适的view,如果没有更合适的子控件,那么自己就成为最合适的view。
找到最合适的view后,就会调用该view的touches方法处理具体的事件。所以,只有找到最合适的view,把事件传递给最合适的view后,才会调用touches方法进行接下来的事件处理。找不到最合适的view,就不会调用touches方法进行事件处理。
注意:之所以会采取从后往前遍历子控件的方式寻找最合适的view只是为了做一些循环优化。因为相比较之下,后添加的view在上面,降低循环次数。
两个重要的方法:
hitTest:withEvent: 方法
pointInside 方法
什么时候调用?
作用
注 意 :不管这个控件能不能处理事件,也不管触摸点在不在这个控件上,事件都会先传递给这个控件,随后再调用hitTest:withEvent:方法
拦截事件的处理
事件传递给谁,就会调用谁的hitTest:withEvent:方法。
注 意 :如果hitTest:withEvent:方法中返回nil,那么调用该方法的控件本身和其子控件都不是最合适的view,也就是在自己身上没有找到更合适的view。那么最合适的view就是该控件的父控件。
所以事件的传递顺序是这样的:
产生触摸事件->UIApplication事件队列->[UIWindow hitTest:withEvent:]->返回 更合适 的view->[子控件 hitTest:withEvent:]->返回 最合适 的view
事件传递给窗口或控件的后,就调用hitTest:withEvent:方法寻找更合适的view。所以是,先传递事件,再根据事件在自己身上找更合适的view。
不管子控件是不是最合适的view,系统默认都要先把事件传递给子控件,经过子控件调用子控件自己的hitTest:withEvent:方法验证后才知道有没有更合适的view。即便父控件是最合适的view了,子控件的hitTest:withEvent:方法还是会调用,不然怎么知道有没有更合适的!即,如果确定最终父控件是最合适的view,那么该父控件的子控件的hitTest:withEvent:方法也是会被调用的。
技巧: 想让谁成为最合适的view就重写谁自己的父控件的hitTest:withEvent:方法返回指定的子控件,或者重写自己的hitTest:withEvent:方法 return self。但是, 建议在父控件的hitTest:withEvent:中返回子控件作为最合适的view!
原因 在于在自己的hitTest:withEvent:方法中返回自己有时候会出现问题。因为会存在这么一种情况:当遍历子控件时,如果触摸点不在子控件A自己身上而是在子控件B身上,还要要求返回子控件A作为最合适的view,采用返回自己的方法可能会导致还没有来得及遍历A自己,就有可能已经遍历了点真正所在的view,也就是B。这就导致了返回的不是自己而是触摸点真正所在的view。所以还是建议在父控件的hitTest:withEvent:中返回子控件作为最合适的view!
例如: whiteView有redView和greenView两个子控件。redView先添加,greenView后添加。如果要求无论点击那里都要让redView作为最合适的view(把事件交给redView来处理)那么只能在whiteView的hitTest:withEvent:方法中return self.subViews[0]这种情况下在redView的hitTest:withEvent:方法中return self是不好使的!
特殊情况:
谁都不能处理事件,窗口也不能处理。
只能有窗口处理事件。
return nil的含义:
hitTest:withEvent:中return nil的意思是调用当前hitTest:withEvent:方法的view不是合适的view,子控件也不是合适的view。如果同级的兄弟控件也没有合适的view,那么最合适的view就是父控件。
寻找最合适的view底层剖析之hitTest:withEvent:方法底层做法
hit:withEvent:方法底层会调用pointInside:withEvent:方法判断点在不在方法调用者的坐标系上。
pointInside:withEvent:方法判断点在不在当前view上(方法调用者的坐标系上)如果返回YES,代表点在方法调用者的坐标系上返回NO代表点不在方法调用者的坐标系上,那么方法调用者也就不能处理事件。
屏幕上现在有一个viewA,viewA有一个subView叫做viewB,要求触摸viewB时,viewB会响应事件,而触摸viewA本身,不会响应该事件。如何实现?
1>用户点击屏幕后产生的一个触摸事件,经过一系列的传递过程后,会找到最合适的视图控件来处理这个事件2>找到最合适的视图控件后,就会调用控件的touches方法来作具体的事件处理touchesBegan…touchesMoved…touchedEnded…3>这些touches方法的默认做法是将事件顺着响应者链条向上传递(也就是touch方法默认不处理事件,只传递事件),将事件交给上一个响应者进行处理
响应者链条: 在iOS程序中无论是最后面的UIWindow还是最前面的某个按钮,它们的摆放是有前后关系的,一个控件可以放到另一个控件上面或下面,那么用户点击某个控件时是触发上面的控件还是下面的控件呢,这种先后关系构成一个链条就叫“响应者链”。也可以说,响应者链是由多个响应者对象连接起来的链条。在iOS中响应者链的关系可以用下图表示:
响应者对象: 能处理事件的对象,也就是继承自UIResponder的对象
作用: 能很清楚的看见每个响应者之间的联系,并且可以让一个事件多个对象处理。
如何判断上一个响应者
响应者链的事件传递过程:
事件处理的整个流程总结:
1.触摸屏幕产生触摸事件后,触摸事件会被添加到由UIApplication管理的事件队列中(即,首先接收到事件的是UIApplication)。
2.UIApplication会从事件队列中取出最前面的事件,把事件传递给应用程序的主窗口(keyWindow)。
3.主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件。(至此,第一步已完成)
4.最合适的view会调用自己的touches方法处理事件
5.touches默认做法是把事件顺着响应者链条向上抛。
touches的默认做法:
事件的传递与响应:
1、当一个事件发生后,事件会从父控件传给子控件,也就是说由UIApplication ->UIWindow ->UIView ->initial view,以上就是事件的传递,也就是寻找最合适的view的过程。
2、接下来是事件的响应。首先看initial view能否处理这个事件,如果不能则会将事件传递给其上级视图(inital view的superView);如果上级视图仍然无法处理则会继续往上传递;一直传递到视图控制器view controller,首先判断视图控制器的根视图view是否能处理此事件;如果不能则接着判断该视图控制器能否处理此事件,如果还是不能则继续向上传 递;(对于第二个图视图控制器本身还在另一个视图控制器中,则继续交给父视图控制器的根视图,如果根视图不能处理则交给父视图控制器处理);一直到 window,如果window还是不能处理此事件则继续交给application处理,如果最后application还是不能处理此事件则将其丢弃
3、在事件的响应中,如果某个控件实现了touches...方法,则这个事件将由该控件来接受,如果调用了[supertouches….]就会将事件顺着响应者链条往上传递,传递给上一个响应者;接着就会调用上一个响应者的touches….方法
如何做到一个事件多个对象处理:
因为系统默认做法是把事件上抛给父控件,所以可以通过重写自己的touches方法和父控件的touches方法来达到一个事件多个对象处理的目的。
事件的传递和响应的区别:
事件的传递是从上到下(父控件到子控件),事件的响应是从下到上(顺着响应者链条向上传递:子控件到父控件。
〖定义〗:所谓的逻辑,用数学语言来说,就是“关系 relation”,按自身循环分类的“一分为二”方法就是 R(·,·)="∈"∪"∉"∪"∅" 。
附图:二维几何模型表示的逻辑类型(变)
所谓的因果,是上面的 R(·,·)="∅" ,其本身是没有端点的,即类似直线。
【问】:
因果链条会一直继续像直线呢?还是会终止像线段呢?
【答】:讨论这个问题,首先要澄清条件,即是否只限制在因果类这个范围之内。
如果只有因果类,不允许有其它类型,那么会一直继续像直线。
如果允许有其它类型,那么会终止像线段。
2010年12月10日中午12点多,与托克逊县佳尔思厂一墙之隔的一家石英厂的老板老王介绍,这里工厂一般10月份就会停工,第二年的3月才会复工,工人每天工资最少150元,而佳尔思厂则完全不同:“一年365天佳尔思厂从来没见停过工,而且这些工人一分工钱都领不到。”
工厂老板李兴林称,自己手续齐全,与四川省渠县乞丐收养所负责人曾令全签订过用工协议,根据协议,每个月向曾令全支付工人工资。 13日晚上23点左右,组织者曾令全被渠县警方以涉嫌非法经营罪刑事拘留。
渠县县委宣传部人士向本报记者介绍,在看到该消息之后,13日晚上,曾令全已被警方控制,经过人力资源和社会保障部门对其用工合法性进行了调查后,警方以涉嫌非法经营罪进行刑事拘留,同时也将该组织取缔。
据媒体报道,曾令全是渠县渠西乡人,出生在一个农民家庭,在家养过猪、卖饲料。外出务工小有积蓄后,1996年创办了渠县渠江镇残疾人自强队,专门收留在垃圾中找食物的智障乞丐,被人遗弃的精神病患者。
渠县宣传部人士表示,所谓渠县残疾人自强队是曾令全个人所创办,民政局不知道有这个事情,该组织名称也是曾令全自己取的,并非官办。在得知这一消息之后,渠县县政府成立由常务副县长、分管民政的蔡文华牵头的联合调查组。
工作组13日晚飞赴新疆,于14日晚到达新疆吐鲁番地区托克逊县,将对被贩卖至此的智障人展开救助和维权。渠县宣传部人士还介绍,明后两天调查组就会发回在新疆的调查情况,当地政府将根据这些调查结果对曾令全采取进一步措施。
同时,四川省民政厅人士向记者介绍,省民政厅也已经责成达州市民政局调查处理。
据媒体报道,2006年湖南耒阳市因一名无名乞丐的死亡而牵出过四川省“渠县乞丐收养所”。当时此事也与曾令全有关,事发后曾令全的妻弟被判刑8年。如果确实,为何这一组织能够继续存在还无人知晓?
上述四川省民政厅人士表示,这属刑事案件,他们并不知情,本报记者多次尝试联系渠县民政局和渠县公安局政委了解具体情况,结果无法联系上。
12月14日,涉嫌组织贩卖“智障包身工”至新疆工厂的四川渠县人曾令全已被渠县公安局刑拘。
事件发生后,渠县有关部门立即赶往曾令全所在的“渠县渠江镇残疾人自强队”,解救了该处16名智障人员,送往县救助站,妥善安置。据了解,从新疆托克逊县库米什镇逃回四川的“黑雇工”雇主李兴林及其子李成龙涉嫌非法用工,已被刑拘。 报道非法奴用新疆智障人士的记者孙虹杰,不幸遇袭罹难
2010年12月18日零时五十分,北疆晨报驻奎屯记者孙虹杰,在奎屯市喀拉尕什小区东方伟业建筑工地东门处被人殴打,手机被抢并摔碎在现场。导致颅内出血,医院已宣告孙虹杰脑死亡,但心脏还在跳动,靠呼吸机呼吸。奎屯警方成立专案组,四十个小时侦破案件,抓获六名犯罪嫌疑人。
对于有关孙虹杰或因舆论监督报道遭打击报复的揣测,《北疆晨报》一位高层人士予以否认,称“不存在打黑英雄的说法”,“不存杂打击报复的情况”。
警方的通报说,审讯查明,犯罪嫌疑人卜某与受害人孙虹杰系网友关系,因孙虹杰与卜某聊天时使用语言不当,卜某心生不满,遂产生收拾孙虹杰的念头。12月17日23时,孙虹杰上网约卜某喝酒,卜某遂与刘某、周某、蒋某、薛某、杨某五人约好,等见面后一起收拾孙虹杰。 工人动作迟缓呆滞
10日中午12点多,一家石英厂的老板老王介绍,这里的工厂一般10月份就会停工,第二年的3月才会复工,工人每人每天工资最少150元,而佳尔思厂则完全不同:“一年365天佳尔思厂从来没见停过工,而且这些工人一分工钱都领不到自己的手上。” 。
中午1点,空地上粉尘没过脚踝,近20厘米厚。距佳尔思厂的粉碎机器10米开外,堆放了大半圈约3米高的做大白粉原料的石材,爬上原料堆,工人们工作的场景清晰可见。一名身着红色破夹袄的工人,将榔头举过头顶,砸向三四十厘米见方的原料石;装车工呆在一边,看石头被砸成小块后,弯下腰一块块捡起,转身扔进手推车。不远处,有工人推着手推车,将原料石运到机器旁。工作区域内,除了喊号声,没人说话;工人们的动作迟缓、呆滞。 从中午1点一直到下午5点,尽管午饭的时间早已过了,但没有人喊工人们吃饭。
工人来自“乞丐收养所”
晚上11点,记者再次来到佳尔思厂。白天停歇的机器开始运转。除了穿红衣的男子,还有4名工人在重复着白天的工作。当晚,机器声轰鸣了一夜。
第二天中午,佳尔思厂外,被老板娘发现。称因为有人举报这里环境污染严重,所以拍照取证。当质疑工人防护措施不足的问题时,他主动表明自己手续齐全,与四川省渠县乞丐收养所,也称四川省渠县残疾人自强队,签订过用工协议。 李兴林说,四川省渠县乞丐收养所的负责人是曾令全,“他组建了乞丐收养所,并向全国输送工人,让那些无法自理或是没有生活保障的人能够自力更生,打工赚钱。”
随后他出示了一份签订于2008年9月9日的《劳务协议》,协议甲乙双方为李兴林和曾令全。规定甲方支付每人每月工资300元,如果甲方丢失乙方队员,每丢失一名赔偿1000元。
“我前前后后已经接过来了30名工人,有些当时看着有劳动能力,来了什么活都干不了,就又送回去了。”李兴林说。
工人与狗同食一锅面
问到工人们的生活状况,李兴林带着记者参观了淋浴室,并一再强调工人们不爱洗澡。厨房一角堆放着24棵大白菜,桌子上放着两尿素袋挂面。
李兴林带着记者推开工人们住的房门:不到10平方米的空间,冰冷而简易。5个房间,每间摆放着两三张床。或用木头拼搭,或是简易的钢丝床。
在工地上。鼻子上挂着片烂布的黑龙江省望奎县人王力,40岁,是工人中沟通最顺畅的。两年间他跑过两回,也被毒打过两回。“第一次都快到托克逊了,被他们开车抓回来了,想跑掉是不可能的。”
正在搬运成品的彭根贵(音)面对问题,重复着这几句话:“一般情况下,只要不违反厂里的规定,就不会挨打。”。“一般情况下,我们干不动的时候,就有肉吃。”“一般情况下,只要不逃跑,就不会挨打。”
中午2点,工人们被老板唤回来。老板娘喊了几遍“吃饭!吃饭!”有人端着白花花的面条高兴地跑出屋子,蹲在墙角直往嘴里倒。“今天的要好点,今天的面里有油!”盛面条的大铝锅放在地上,老板娘一勺一勺舀给工人。两条狗进进出出,时不时把头抻进锅里,舔着面条。老板娘举着大勺,冲狗叫了一声,见狗并不离开,也就不再管了。
工作环境
没有工资领的“劳动机器”
2010年12月10日,冬天的戈壁滩十分苍凉,冷风打在脸上像刀割一样。托克逊县库米什镇工业园区内大部分厂子已经歇工,工人都回家了……但在托克逊县库米什绿色建材化工厂“智障工”依旧在工作。 附近的一家工厂的看门人说,工业区的工厂一般每年的10月份就会停工,来年三月份才会复工,因为劳动强度大,工人的每天的工资最少要150元,否则根本没人干,但是库米什绿色建材化工厂几乎是全年生产。“他们厂里的工人不需要付工钱,吃的也差,很惨。”说这话时,他的眼神充满了怜悯。
在现场看到,工厂内粉尘飞扬,工人破旧的衣服上落了厚厚的一层粉尘,工人在没有任何保护的情况下,用锤子把石料敲成小块,然后用车将石料送到粉碎机……简单、重复的劳动,呆滞的眼神,没有一个人说话。 对于托克逊县库米什绿色建材化工厂使用“智障工”的行为,该厂老板李兴林表示,在这里可以吃上饭,从某种程度上说,还是行善。
当问到这些工人是从那里来的?库米什绿色建材化工厂厂长李兴林说:“2008年,10个人全都是从四川省渠县残疾人自强队一个叫曾令全的人手下招过来的。”随之,李兴林向我们展示了曾令全一同在四川省渠县残疾人自强队挂牌下照的相片和一张打款收据。
问他们每个人叫什么名字,李兴林笑着说,他们傻乎乎地说不清楚,怎么能知道他们的名字,说着还用双手向记者进行比划。这些人在外边得不到温暖,在这里有饭吃,我们还有监护权。一天不停地看着他们才安全。丢了,还得自己出去找。万一出去冻死了怎么办?
李兴林说,这些人既没有办残疾人证,也没有身份证,保险公司不敢担保。自己想给办个团体残疾证,因为万一出上个事情就麻烦了。没有身份证就不了了之。李兴林说:“这些人,站时是个光鸡蛋,死了就是方块块。”记者说没明白这句话的意思时,李兴林补充道:“活着的时候不值钱,死了就值钱了。”
李兴林表示自己工厂内现在一共10个人,每天实行两班倒,这些都是经过一段时期的使用符合劳动条件才留下来的。记者问给工人是否发放口罩以及棉衣棉裤等越冬的必备品时,李兴林的妻子从一个房间里拿出两只口罩说:“口罩有,他们就是不习惯戴。”
李兴林带着记者来到工人们居住的房屋,记者看到一间不到10平米的房间,冰冷而简陋。5个房间,每间摆放着两三张床。或用木头拼搭,或是简易的钢丝床。凌乱蜷缩着的肮脏被子,轻轻一提就能拎起来;有些床上的褥子就是一层薄薄的床单,有的就只是铺了层硬纸壳。
一个名叫刘双辉的工人把所有的衣服穿在身上避寒,破损的毛衣下还穿着4件单衣,被子上压着一件军大衣。被问到是否领过工钱,已经干了4年活的刘双辉低下头搓着手:“还没跟老板说呢。”“第一次都快到托克逊了,被他们开车抓回来了,想跑掉是不可能的。”名叫王立的工人是所有工人中,表达能力最强的,他告诉记者,自己40岁,来自黑龙江望奎县,两年间他跑过两回,也被毒打过两回。两年没有洗过澡,回家是他最大的愿望。
李兴林最后说,过年的时候,他想把这些人送回四川去。 利益驱使构成非法用工链
对非法用工的问题,李兴林主动表明自己手续齐全,与四川省渠县乞丐收养所(也称四川省渠县残疾人自强队),签订过用工协议。
李兴林拿出2008年9月9日,李兴林和曾令全签订的《劳务协议》,上面没有任何公证机关的证明,只有两人的指印。在“协议书”上,赤裸裸显示着一条令人震惊的黑色“财富链”:经甲(李兴林)、乙(曾令全)双方协商,甲方用乙方(渠县残疾人自强队)第二批队员5名。而此协议上,前面的人员按前面订的协议不变,继续实行。在签字之日起,一次性支付5名队员半年工资9000元,所欠工资于2008年10月15日起,每月付750元,到2009年9月15日付完。第二批队员5人,每月每人工资300元。第二批5名队员,2008年9月15日至2009年9月15日期间,每人工资3600元,不论在任何情况下,也不管有没有活干。甲方必须给乙方付清工资。
在这条充满血泪的财富链条的一端,是四川省渠县一个名叫曾令全的“渠县残疾人自强队”负责人。此人从社会上“收集”流浪汉后送到建材厂当工人,这些人的工资全由其代理人领取后汇到他的账户上。而在链条的另一端,建材厂的老板可以用比市场低得多的人工成本,来完成生产任务。
从《劳务协议》中我们看到,2008年年初,李兴林夫妇承包了托克逊县库米什绿色建材化工厂,同年9月,李兴林同曾令全签订了劳动合同,由曾将渠县“残疾人自强队”的5名流浪乞讨人员带到托克逊县库米什绿色建材化工厂做工,委托李兴林负责管理。
法律分析:公安常见刑事案件证据链条构建及证据清单主要包括:(一)物证;(二)书证;(三)证人证言;(四)被害人陈述;(五)犯罪嫌疑人、被告人供述和辩解;(六)鉴定意见;(七)勘验、检查、辨认、侦查实验等笔录;(八)视听资料、电子数据。
法律依据:《中华人民共和国刑事诉讼法》 第五十条 可以用于证明案件事实的材料,都是证据。证据包括:(一)物证;(二)书证;(三)证人证言;(四)被害人陈述;(五)犯罪嫌疑人、被告人供述和辩解;(六)鉴定意见;(七)勘验、检查、辨认、侦查实验等笔录;(八)视听资料、电子数据。证据必须经过查证属实,才能作为定案的根据。
“天价鳇鱼”舆论三度反转 距离真相越来越近
针对哈尔滨“天价鳇鱼”事件,松北区的专项调查组15日发布通告。但官方的调查结论出台后,公众继续从多个角度对这一事件进行质疑,当事消费者也指出菜单签字造假、鱼的斤两存在问题等。很明显,这一调查结果并未打消公众的疑虑,“天价鱼”事件尚有诸多疑窦待解。
纵观整个“天价鳇鱼”事件,48小时内舆论已三度反转。针对公众提出的,饭店所售鳇鱼是否野生、定价是否合理、导游和出租车司机引导消费是否存在利益输送链条、饭店网上美誉度为何极低等疑问,当地有关部门应当继续深挖,给当事人和公众一个说法。
16日,哈尔滨“万元吃鱼”事件再掀波澜,当地官方15日晚通报涉事渔村“明码标价不违规”,随即被爆出同时同地该渔村又一“天价吃鱼”事件,出现了此前未在涉事渔村菜牌中出现的“鳇鱼头498元/斤”;就在同一天,江苏游客陈岩在南京通过媒体发声称渔村公布的手写账单“不是我签的字”、“遭店家恐吓,孩子被人肉”等,对官方调查结果提出质疑。同时,据《新京报》报道,有当地导游曝出内幕,称带人到“天价鱼”餐厅能拿60%提成。
至此,手写账单上的“陈姓”签字到底出自谁手?北岸野生渔村叫卖的“野生鱼”是否真的野生?鱼的斤两是否存在问题?鱼的定价是否合理?导游和出租车司机引导消费是否存在利益输送链条等5大焦点问题被抛了出来。究竟真相如何,一起去看看事件当事人都是怎么说的。
4大焦点
当媒体在热炒这起事件的时候,作为发帖当事人的陈岩却选择了关机,并删除了相关的微博。他的举动一度引发了众人的猜疑,甚至有人认为他是心虚。也因为这个原因,他在网上遭到了各种“抨击”。网友为此展开了骂战,将一起消费事件上升到了地域攻击。
昨日,当事人陈岩现身说法,针对网上提出的质疑,他一一回应。
鱼到底是14.4斤,还是10.4斤?当事人:“人格担保是10.4斤”
就一直备受关注的鳇鱼斤两问题,涉事饭店曾在15日表示,他们给鳇鱼称重14.4斤,顾客结账时说是10.4斤,江苏顾客南方口音很重,双方就“四”和“十”的字音上出现了纠纷,店方推断称是南北口音辨别上产生了误会。
昨天早上8点42分,记者拨打天价鱼事件的当事人——常州游客陈先生的手机。在关机一天多后,电话终于通了。
电话中,陈先生回答了记者几个问题。他说,当初微博上发的内容完全属实,鳇鱼的斤两,还是10.4斤,店方说14.4斤,绝对是搞错了。“过秤就是10.4斤,我可以拿人格担保,亲眼所见。”
去吃鱼是不是公款消费?消费者是常州个体户非公职人员
陈先生婉拒了当面采访的要求。他回应了部分网友的疑问,他说自己是常州当地的个体户,并不是公职人员,和家人去哈尔滨旅行是自费。
对于网友的质疑“实付7200元,为何却说是10302元?”陈先生说,买单不是我买的,第二天我知道的时候也没看收据,后来我发现的时候,各大报道已经出来了。首先在这里我承认,店家在我们被打之后,主动打了七折。
是自己去的,还是导游带进店?陈先生:旅行社说要给我们赔偿
在接受黑龙江当地电视台采访时,当事饭店北岸野生渔村强调,陈先生一行人是自己去的饭店。
而陈先生予以否认,他说自己的团队是被导游带去的。
陈先生说,“当地的旅行社不断跟我们道歉,不断(说要)给我们赔偿金额,我们一直不接受。我们是这样想的,既然事已经出了,我们也不要别人赔偿,既然你犯错了,你就要承担你犯错误的责任,我是抱着这个态度发的帖子。”
昨天,常州当地一家电视媒体还播出了陈先生接受采访的内容。在视频中,关于谁先动手的问题,陈先生称,“网上都是说我喝醉酒我先动手,但警察可以从监控中看出我是被打的。”他说,调解后和老板拥抱是不想被报复。
对于在微博上写了黑东北一词,陈先生也通过媒体表示歉意:“在这个方面我考虑不周,我不应以区域性来划分。毕竟不良商家是个别的,在这里我通过媒体向东北人民道歉。”
为何删帖关机玩“消失”?遭店家恐吓孩子信息被曝光
至于有网友质疑他为何删帖关机,陈岩说,自从事情发生后,就不断接到各种电话,特别是黑龙江那边的电话,“我实在是受不了,生活完全被打乱,没办法,只能把手机关掉,微博也删了。”
他还称,自己发微博就是吐槽提醒下,没想到完全性的失控,“发了微博以后,店家还打电话来恐吓我们,这个可以提供通话记录,甚至我们家人孩子的信息被他们人肉发到网上,在此我请求哈尔滨网警能够依法处理,不管这件事情如何,家里的老人,我的未成年的女儿是无辜的,这个对他们的打击很大。”
记者调查
“天价鱼”被曝光前,许多游客在网络上吐槽称是经当地司机推荐到涉事饭店就餐,消费几千上万元,花了几千元吃顿鱼连张发票都没有,他们手中仅有收银小票。那么,打着“北岸野生渔村”招牌的饭店,究竟有没有经营野生鳇鱼的经营许可证?
游客是否签字确认过消费账单?饭店承认字为服务员代签
一张手写账单上的“陈”字,也成为双方争执的关键一环。陈先生表示,“那肯定不是我签的字,这个可以做笔迹鉴定!”而据媒体报道,昨天与涉事饭店北岸野生渔村饭店核实后得到了新答案。前台经理赵玲承认,在手写账单上签字的并不是游客陈先生本人,而是该店服务员为“免责”代签了“陈”字。
天价鳇鱼店没有违规?餐饮许可过期,工商注册无野生字样
据媒体报道,昨天下午在全国企业信用信息公示系统查询后发现,打着“北岸野生渔村”招牌的涉事饭店工商登记名称实际为“哈尔滨市松北区北岸渔村饭店”。经营者为马某某,经营场所为松北区新新怡园小区2号楼2号商服,经营范围有中餐类制售:主食,凉菜(不含裱花蛋糕、不含生食海产品),餐饮服务许可证有效期为2013年2月5日至2016年2月4日。登记状态为存续。
由此可见,该饭店餐饮许可已过期,而工商登记的经营范围并没有“野生”。
某点评网站上,北岸野生渔村的地址与工商注册地址一致。
当地市场鳇鱼咋卖?加工的30元一斤,养殖的10元一斤
昨天上午,记者来到位于哈尔滨兆麟街的大型菜市场——道里菜市场,在这里,记者见到了一种已经加工过的鲟鳇鱼,摊主称,这是一种开袋即食的成品,30块钱1斤。另一位摊主告诉记者,在附近的哈达友谊农贸市场,可能会有鳇鱼出售。
记者随后在哈达市场内看到,有一家鱼行在出售一种养殖的鳇鱼,老板娘说,这种鱼只要10多元1斤,一条重四五十斤。老板娘表示,她也看了新闻,新闻里说的398元1斤的鳇鱼,是那种200斤左右的野生鳇鱼,价格很贵。在这个季节很少,一般市场是没有卖的。一年多前,她曾经卖过,当时卖100多元1斤。如果是只买中段,价格更贵。
另一个水产摊的老板说,他卖过上百斤的鳇鱼,最贵的80块钱1斤。
事件反转饭店咋说?“饭店老板和经理都生病去打针了”
昨天下午2点多,记者再次来到北岸野生渔村,当时,店内灯光昏暗,没有顾客。一位男工作人员表示,没有什么生意。店老板和在年初二那天值班的经理赵玲都不在店内。一位女服务员称,他们都生病了,都去医院打针了。
昨天有媒体记者致电渔村老板马某,追问所售鱼类究竟是野生,还是养殖?马某在电话中对记者说:“这件事让我受到了很大打击,正在打点滴,不想再接受采访了。”
经过沟通协调,昨天下午3点多,哈尔滨松北区调查组方面和常州游客陈先生通了电话。
调查组一位姓赵的工作人员告诉记者,双方通话约20分钟,陈先生讲述了事情的经过。
赵先生表示,他会将陈先生讲述的情况形成一个书面材料,向上级领导汇报。之前只是从饭店方面进行了调查,是一个初步调查的情况。
对网友关注的野生鳇鱼经营是否合法、当事饭店经营的鳇鱼到底属于什么性质等问题,赵先生表示,调查组方面会进一步展开调查,并将公布调查结果。
昨天中午,记者来到松北区委宣传部,新闻科负责人尹玉堂通过记者联系上了陈先生。尹玉堂表示,2月15日公布的调查结果,只是初步结果,没有消费者陈先生方面的说法,现在会进一步深入调查。
尹玉堂介绍,松北区有关部门在网上看到陈先生微博反映的情况后,就立即成立了由市场监督管理局、旅游局等成立的调查组,并赶往店方去调查。
在调查现场,调查组调取了包括监控录像以及相关票据、许可证等证据。
食客吐槽
到涉事饭店吃鱼多是被导游司机推荐
据媒体报道,昨天上午,一名哈尔滨匿名导游小丽(化名)爆料称,自己曾经做过导游,往上述渔村带人会有60%左右的提成。不过此说法未得到店家的证实。
此前,已有不少游客在网络上反映,到涉事饭店吃鱼均是通过当地承接旅行社导游、司机以及出租车和一些黑车司机推荐。
“从冰雪大世界出来,坐辆出租车,司机就拉到了这里。”游客林小姐告诉记者,去年11月,她和朋友到哈尔滨旅游时,就被出租车司机带去北岸野生渔村吃鱼。
林小姐说,按照经验,通常相信当地人推荐美食,没想到被“宰”。“鳇鱼很大一条,光是鱼头就10几斤,我们只吃了几斤鱼,就消费3000多元。”
“被司机骗来的,地方特别偏僻。”国内某著名美食点评网上“北岸野生渔村”获评只有两颗星,其下方有200多条评论,大部分评价其口味一般,价格过高。有食客在今年的大年初一评论说,“味道不错,不过价格真是一下子吓死宝宝了,一顿饭一万啊,后面吃泡饭了,算自己开眼界了。”
不少食客都在评论中称,自己是被当地出租车司机介绍到餐厅的。有网友吐槽称,一下飞机就被拉到了这里。还有食客称,有司机反映只要介绍客人进店将会得到一定提成,通常在几百元左右。
再起风波
又是这家店!
游客再曝吃顿鱼近 1.6 万元
常州陈先生在哈尔滨吃鳇鱼消费上万元这事还没完,又有游客爆料,就在同一家店,同一时间,浙江的王女士一行19人,消费了近16000元,其中最贵的鳇鱼鱼头售价达498元一斤。
15日上午,浙江的王女士反映,2月9日晚,陈先生与店家发生争执时,她正在北岸野生渔村二楼就餐,一行19人(不包括导游和司机)点了30多斤鱼。一结账懵了,竟要15735元。王女士一行也点了店家推荐的名贵野生鳇鱼,并且是鳇鱼头,每斤498元。仅这一份鱼头就花了近8000元。
王女士称自己也是被导游带去渔村的,“称鱼时被口头告知价格。”王女士一行人在结账时发现陈先生等顾客与店家发生争执拉扯,看到自己接近1万6的账单也很“震惊”,而邻桌的6人旅行团消费也近万元。
“我们对斤两也有怀疑,但当时警察来了,导游和司机说他们在打架不安全,要我们马上结账。”王女士称,30多斤的鱼只吃了三分之一,只能买了盆子把剩下的鱼打包带走。
目前,松北区旅游局已经联系到王女士进行询问调查,目前王女士一行在与旅行社协商赔偿,等待调查结果。
浙江游客王女士等人消费了15735元的菜品中,其中出现了一道“新菜”——“鳇鱼头铁锅炖”,票据显示鳇鱼头单价为498元/斤,总价为7918元。
记者15日在北岸野生渔村采访中,并未在“鱼类展示柜”发现关于“鳇鱼头”的单独标价;而在当日营业时,鳇鱼头也并未在渔村公示的易拉宝菜牌上“明码标价”。但当记者16日13时再访该渔村时,其易拉宝菜牌仍没有鳇鱼头的标价,但在“鱼类展示柜”上新增了一个“黄色纸壳价签”,黑笔手写“鳇鱼头498元/斤”。
立即评
以公允调查回击“天价鱼”式的消费陷阱
数日发酵之后,“天价鱼”事件非但没有尘埃落定,反倒越发疑云满布。在连番反转、再反转之后,所谓的是非对错,正慢慢变得模糊含混。由于“笔迹争议”等新看点的加入,这场普通而严肃的消费纠纷,俨然正滑向全民侦探剧的庸俗剧情。一面是几乎一边倒的官方调查结论,另一面却是民间持续不断的举证、批判与质疑。当事人陈岩最新的火爆发声,无疑将两方阵营、两种意见的拉锯,又推向一个高潮。
事实上,在哈尔滨松北区公布调查报告之际,曾经直言“未能联系到当事人”,并称希望其主动与之联系,还原事件原貌。从这一细节不难看出,当地官方对于自己所给出的“结论”,还是留有足够的回旋余地!如今,陈岩隔空回应,自然是对后续调查的一大利好。我们期待着,当地相关职能部门,能够秉持公允立场、拿出最大的诚意,争取尽快与陈岩取得直接接触,继而在采纳各方说辞、严谨核实甄别之后,最终给出令人信服的调查结论。
在15日,当地调查者仅仅凭着店方的一面之词,就急不可耐抛出疑点重重的“调查报告”,这本身就显得很是诡异。在很多人看来,此一举动颇有地方保护主义,以及“危机公关、维护形象”之嫌!如此这般,过程存疑、结论偏颇的“调查”,不仅未能平息众怒,反而会加剧焦虑。再加之,由此衍生的地域污名化和露骨的人身攻击,更是使得“天价鱼”事件一步步复杂化、情绪化。
或许,尤需厘清的一点在于,“天价鱼”事件无关其他,本质还是一起消费纠纷。评判其中是非曲直,要基于事实真相,要基于法律界定,更要基于市场常识。当地调查组表示,涉事餐馆明码标价,故而不涉及违规——这套逻辑看似有理,其实并不能站住脚。这是因为,陈岩系旅行社“引导”进店消费。陌生的消费场景,陌生的消费对象,这一切都决定了,陈岩被置于刻意营造的信息不对称状态,故而很难做出理智的判断与选择。
“天价鱼”事件,有别于一般的宰客事件,就在于它乃是一种共谋式、链条化的消费陷阱。捍卫消费公平,绝不是做到明码标价那么简单。更重要的是,要保护消费者充分运用理性、审慎做出决定的权利。但愿“天价鱼”事件的后续调查,能够对此有所说明。本组稿件综合新华社、《新京报》、中国日报、常州电视台等。
1.发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的队列事件中
2.UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常会先发送事件给应用程序的主窗口(keyWindow)
3.主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件
事件的具体传递过程,如图:
一般事件的传递是从父控件传递到子控件的
例如:
点击了绿色的View,传递过程如下:UIApplication->Window->白色View->绿色View
点击蓝色的View,传递过程如下:UIApplication->Window->白色View->橙色View->蓝色View
如果父控件接受不到触摸事件,那么子控件就不可能接收到触摸事件
应用如何找到最合适的控件来处理事件?有以下准则
详述:
1.主窗口接收到应用程序传递过来的事件后,首先判断自己能否接手触摸事件。如果能,那么在判断触摸点在不在窗口自己身上
2.如果触摸点也在窗口身上,那么窗口会从后往前遍历自己的子控件(遍历自己的子控件只是为了寻找出来最合适的view)
3.遍历到每一个子控件后,又会重复上面的两个步骤(传递事件给子控件,1.判断子控件能否接受事件,2.点在不在子控件上)
4.如此循环遍历子控件,直到找到最合适的view,如果没有更合适的子控件,那么自己就成为最合适的view。
UIView不能接收触摸事件的三种情况:
寻找最合适的view过程,如图:
这里点击了橙色的那块区域,事件传递判断过程如下:
1.UIApplication从事件队列中取出事件分发给UIWindow
2.UIWindow判断自己是否能接受触摸事件,可以
3.UIWindow判断触摸点是否在自己身上,是的。
4.UIWindow从后往前便利自己的子控件,取出白1(a.UIWindow的子控件只有一个,那就是白1)
5.白1都满足最上面两个条件,遍历子控件橙2
特别说明:
( a.白1的子控件有两个,绿2和橙2 )
( b.添加顺序是,先添加绿2,后添加橙2 )
( c.根据后添加的子控件先遍历的原则,肯定是先遍历橙2子控件 )
6.橙2都满足最上面两个条件,遍历子控件,先取出红3
( a.橙2的子控件有两个,蓝3和红3,注意黄4不属于橙2的子控件而是蓝3的子控件 )
( b.添加顺序是,先添加蓝3,后添加红3 )
( c.根据后添加的子控件先遍历的原则,肯定是先遍历红3子控件 )
7.红3不满足条件2,取出蓝3
8.蓝3也不满足条件2,最后最合适的控件是橙2
寻找合适的View用到两个重要方法:
什么时候调用?
只要事件一传递给一个控件,这个控件就会调用他自己的hitTest:withEvent:方法寻找合适的View
作用
寻找并返回最合适的view(能够响应事件的那个最合适的view)
注 意:不管这个控件能不能处理事件,也不管触摸点在不在这个控件上,
事件都会先传递给这个控件,随后再调用hitTest:withEvent:方法
hitTest:withEvent:底层调用流程:
事件传递给窗口或控件后,就调用hitTest:withEvent:方法寻找更合适的view。所以是,先传递事件,再根据事件在自己身上找更合适的view。
不管子控件是不是最合适的view,系统默认都要先把事件传递给子控件,经过子控件调用自己的hitTest:withEvent:方法验证后才知道有没有更合适的view。即便父控件是最合适的view了,子控件的hitTest:withEvent:方法还是会调用,不然怎么知道有没有更合适的!即,如果确定最终父控件是最合适的view,那么该父控件的子控件的hitTest:withEvent:方法也是会被调用的。
以上是事件传递的顺序:
上文介绍了事件的传递过程,找到合适的View之后就会调用该view的touches方法要进行响应处理具体的事件,找不到最合适的view,就不会调用touches方法进行事件处理。
这里先介绍一下响应者链条:响应者链条其实就是很多响应者对象(继承自UIResponder的对象)一起组合起来的链条称之为响应者链条
一般默认做法是控件将事件顺着响应者链条向上传递,将事件交给上一个响应者进行处理 (即调用super的touches方法)。
那么如何判断当前响应者的上一个响应者是谁呢?有以下两个规则:
1.判断当前是否是控制器的View,如果是控制器的View,上一个响应者就是控制器
2.如果不是控制器的View,上一个响应者就是父控件
响应过程如下图:
touch响应:
如果控制器也不响应响应touches方法,就交给UIWindow。如果UIWindow也不响应,交给UIApplication,如果都不响应事件就作废了。
最后总结来说一次完整的触摸事件的传递响应过程为:
UIApplication-->UIWindow-->递归找到最合适处理的控件-->控件调用touches方法-->判断是否实现touches方法-->没有实现默认会将事件传递给上一个响应者-->找到上一个响应者-->找不到方法作废
一句话总结整个过程是:触摸或者点击一个控件,然后这个事件会从上向下(从父->子)找最合适的view处理,找到这个view之后看他能不能处理,能就处理,不能就按照事件响应链向上(从子->父)传递给父控件
额外添加:
有了响应网为基础,事件的传递就比较简单,只需要选择其中一条响应链,但是选择那一条响应链来传递呢?为了弄清真个过程,我们先来查看一下从触摸硬件事件转化为UIEvent消息。
首先用户触摸屏幕,系统的硬件进程会获取到这个点击事件,将事件简单处理封装后存到系统中,由于硬件检测进程和当前运行的APP是两个进程,所以进程两者之间传递事件用的是端口通信。硬件检测进程会将事件放入到APP检测的那个端口。
其次,APP启动主线程RunLoop会注册一个端口事件,来检测触摸事件的发生。当时事件到达,系统会唤起当前APP主线程的Runloop。唤起原因就是端口触摸事件,主线程会分析这个事件。
最后,系统判断该次触摸是否导致了一个新的事件, 也就是说是否是第一个手指开始触碰,如果是,系统会先从响应网中 寻找响应链。如果不是,说明该事件是当前正在进行中的事件产生的一个Touch message, 也就是说已经有保存好的响应链。