iOS 关键知识点

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

上一篇下一篇

猜你喜欢

热点阅读