iOS学习之响应链

当用户点击到页面上的视图:

1.系统(OS)检测到点击事件,将点击信息包装成UIEvent事件对象

2.系统将该事件对象放到当前活跃APP的事件队列之中

3.单例UIApplication从事件队列中拿到该事件对象,并将其传给key window

4.Key window调用hit-test去找出第一响应者.

a.hit-test调用pointInSide方法,如果pointInSide判断点击的点落在该视图之内,返回true,否则返回false

b.当返回true时,将该响应链入栈,hit-test去递归调用其子视图的hit-test方法

c.当返回false后,hit-test方法在该级返回nil,然后去调用该view的兄弟视图的hit-test方法

依此方法,直到找到最小的叶子节点(这并不代表页面里的所有的view的hit-test都会被执行)

5.通过这样的查找,会形成一个响应链条,即所有hit-test方法返回view(非nil)的对象都在该链中。然后,系统按后进先出的顺序测试响应链中的元素(即从找出的最小的叶子节点开始测试),看看哪一个能处理该点击事件。如果能处理,则该点击事件交由它处理,如果不能,继续去查看该链的下一个节点是否能响应,直到UIApplication对象,如果都不能响应,则该事件被放弃处理。


在自定义hit-test方法时需要注意:

1.hit-test方法最好不要返回self.(如果点击的是该视图上的子视图时,正常情况下会返回其子视图的view而不是自己)

2.pointInSide与hit-test的关系。(正常情况下,如果pointInSide返回false,则hit-test会返回nil。但如果你直接在hit-test里写死返回的东西,那其实pointInSide返回值就无意义,所以最终系统会看hit-test返回的view是否为nil,而不关心pointInSide的返回值)

3.在hit-test里最好不要把返回值写死(只要你点击,它几乎都会响应)

其hitTest方法更像是这样的:

func hitTest(_ point:CGPoint, with event:UIEvent?) ->UIView? {

        var touchedView:UIView?

        let result = self.point(inside: point, with: event)

        if result == true {

            for view in self.subviews{

                touchedView = view.hitTest(point, with: event)

if touchedView != nil{

break

}

            }

        }

        /*

         用户override重写该方法,如果用户为touchedView赋非nil值,则该view仍将出现在响应链中

         */

        return touchedView

    }



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值