Swift - 事件传递链和响应链
2016-04-17 本文已影响769人
离子来了
事件传递链
定义:操作系统,逐级找到第一响应者对象的过程
Paste_Image.png上图的描述:
1.操作系统将事件打包成event对象,传递给当前活跃的app(UIApplication)中的事件队列中
2.由UIApplication来进行事件的分发,首先传递给keywindow,然后逐级查找第一响应者。哪个view的hitTest:withEvent:方法返回非 nil那么第一响应者就是哪个View
查找第一响应者主要用到UIView中的2个方法,已经模拟重写:
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
var tmpView:UIView? = self
let subviews = self.subviews
let reverseView = subviews.reversed()
for subview in reverseView {
let tmpPoint = subview.convert(point, from: self)
if subview.point(inside: tmpPoint, with: event){
let view = subview.hitTest(tmpPoint, with: event)
if let sv = view {
tmpView = sv
break
}
}
}
return tmpView
}
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
if self.alpha <= 0.01 || !self.isUserInteractionEnabled || self.isHidden {
return false
}
return self.bounds.contains(point)
}
事件响应链
定义:第一响应者对象如果不能响应事件(event),事件将逐级向上找到传递,直至丢失
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
print("touch begin B")
var firstReponder:UIResponder? = self
while(firstReponder != nil)
{
print(firstReponder!.description)
firstReponder = firstReponder?.nextResponder()
}
}
输出结果如下 :
<iOSComponent.UIViewB: 0x12f701110; frame = (33 98; 240 128); autoresize = RM+BM; layer = <CALayer: 0x12f627f70>>
<iOSComponent.UIViewA: 0x12f700880; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x12f6f04d0>>
<iOSComponent.ResponderChainViewController: 0x12f700370>
<UIViewControllerWrapperView: 0x12f5745e0; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x12f56db40>>
<UINavigationTransitionView: 0x12f69d840; frame = (0 0; 375 667); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x12f6cc970>>
<UILayoutContainerView: 0x12f6e5d70; frame = (0 0; 375 667); autoresize = W+H; gestureRecognizers = <NSArray: 0x12f606260>; layer = <CALayer: 0x12f6cbed0>>
<iOSComponent.BaseNavigationController: 0x12f813000>
<UIViewControllerWrapperView: 0x12f69e570; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x12f6ea0e0>>
<UITransitionView: 0x12f6e1080; frame = (0 0; 375 667); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x12f6a7b20>>
<UILayoutContainerView: 0x12f6e0ce0; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x12f6a7a10>>
<UITabBarController: 0x12f6a3140>
<UIWindow: 0x12f6de250; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x12f506d30>; layer = <UIWindowLayer: 0x12f6dbdc0>>
<UIApplication: 0x12f610fe0>
<iOSComponent.AppDelegate: 0x12f513950>
响应者对象
iOS中一切只要是UIResponder的对象,都叫可作为响应者对象,响应事件
iOS中UIResponder的直接子类常用的有:
1.AppDelegate
2.UIApplication
3.UIWindow
4.UIViewController
5.UIView