iOS下响应链机制

关于iOS的响应链

测试妹子给我挂了一个Bug,原因是那个隐秘按钮热点区域太小,点击不够顺畅。我仔细定位了一下,发现确实是妹子的手指太大,不够秀巧,刚想驳回,转眼一想有一个增加热点的办法,故进行了尝试。

其实,这是个老生常谈的话题,iOS下的事件传递机制,事件响应是根据响应者链条进行传递的,根据官方文档描述,见图

说干就干。

这个隐藏密码的眼睛,即便调大了也并不能增加多少热点区域,所以我打算把这个按钮往右边偏移一部分,成为这样:

.

.

但是这样多出来的并不能点击,这还要涉及响应者链条问题。

首先,要知道的是,要让按钮可以相应,就必须让按钮成为hit-test-view,就是说,只有hit-test-view才能相应事件。根据文档,当你点击了屏幕上的某个view,这个动作由硬件层传导到操作系统,然后又从底层封装成一个事件(Event)顺着view的层级往上传导,一直要找到含有这个点击点且层级最高(文档说是最低,我理解是逻辑上最靠近手指)的view来响应事件,这个view就是hit-test-view。

决定谁hit-test view是通过不断递归调用view中的 - (UIView *)hitTest: withEvent: 方法和 -(BOOL)pointInside: withEvent: 方法来实现的。- (UIView *)hitTest: withEvent:方法是用于传递事件,而 -(BOOL)pointInside: withEvent:用于判断触摸点是否在自身范围内。

对于传递的顺序以及调用过程,可以参考demo ,找到hit-test view后,它会有最高的优先权去响应逐级传递上来的Event,如它不能响应就会传递给它的superview,依此类推,一直传递到UIApplication都无响应者,这个Event就会被系统丢弃了。

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
    
    CGPoint currPoint = [self convertPoint:point toView:self.showPwdBtn];
    
    if ([self.showPwdBtn pointInside:currPoint withEvent:event]) {
        if (![self.showPwdBtn isHidden]) {
            return self.showPwdBtn;
        }
    }
   CGPoint currPoint2 = [self convertPoint:point toView:self.clearBtn];
    
    if ([self.clearBtn pointInside:currPoint2 withEvent:event]) {
        if (![self.clearBtn isHidden]) {
            return self.clearBtn;
        }
    }
    return [super hitTest:point withEvent:event];
    
}

所以我在按钮的父类加上方法判断是否在当前点击,这样就能找到对应的hit-test-view了,但是还有一个问题,那就是层级问题,hit-test-view是通过这个Controller的view的subviews按照从后往前的顺序来寻找hit-test-view的,所以,[self bringSubviewToFront:self.passwordInputField];这样就是将层级提高到最前面,就是离手指最近,也就是subviews的最后面。

.

这样隐藏密码的按钮就可以响应事件了。现在来看层级结构图,我们之前认为最上面的就是可以点击的,事实上最上面的就是subvuews的最后一个啊,而hit-test就是从后往前找,这样来看,是不是就清楚多了。

最近的文章

临时邮简介

背景在某一日,终于收到了无数封垃圾邮件的我彻底分裂,一天之间私人邮箱收到数百封未读邮件。而与之绑定的手机客户端,每隔十几分钟就要提醒有邮件收到,烦人的广告,无法关闭的退订,以及琳琅满目的各类诱惑性邮件,让我彻底放弃了一个使用了十几年的邮箱。而这件事件让我对邮件有了新的看法,在数日的调研和观察中,我有了一个想做一个App的想法,去帮助被垃圾邮件困扰的人,以及如何有效的在信息纷杂的今天快速获取想要的信息。这大概就是“临时邮”制作的初衷:让这个世界少一点垃圾。它是什么“临时邮”这个项目是一个为解...…

继续阅读
更早的文章

给博客地址Http协议加个s

由于域名到期,目前我的blog将暂时使用http协议。这篇文章,是我去年做到https留下的记录,确实可以做到文中所述。让人无奈的运营商偶然间发现打开博客,弹出了一个底部toast广告,虽然只有短短数秒,但显示内容居然是18禁的东西,我秉着认真负责的态度,为广大读者以身试法点开了,居然要某快播变种软件,下载后发现居然是exe,没有Mac对应平台!这种打着发福利变相谋私利的禽兽,真的是太让人生气了。所以我决定,给自己的博客加个s,保证不在传输过程中被添油加醋。GitHub Pages最近已经...…

继续阅读