重新认识UIButton

3,065 阅读3分钟

背景

本文是修复了UIControl和UITapGestureRecognizer冲突bug后,对UIButton的深入了解

Bug现场

在我的项目里有类似这样一张视图结构的卡片

如图所示:

  • 蓝色视图上面添加了一个手势
  • 斧头图片的superView是蓝色视图,它上面放了一个UIButton
  • 下面黄色视图斧头图片平级,superView也是蓝色视图,上面放了一个UIControl

故事情结

当我愉快的写完这个UI,三下五除二的自测了一翻,嗯,很完美,提测。

周五晚上,我正准备下班的时候,测试同学忽然给我报了一个bug,右下角的UIControl跳转逻辑,走到了下面手势跳转的逻辑

我心想这怎么会错呢,我之前自测都是好的,再说右上角的跳转都没有问题

然后打开Xcode调试了一番,确实有问题

右上角UIButton跳转是好的,UIButton继承至UIControl,按道理他们的事件处理逻辑是一致的啊,但用UIControl自定的UI跳转确实出了问题,

由于时间紧急,我也没有深入研究,只能先修复再说

修复代码

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    return ![touch.view isKindOfClass:UIControl.class];
}

这段代码逻辑很简单,就不废话了

Debug

在上线后,我一直在纠结这个点,就深入研究了一下,接下来探讨一下为什么会导致这个Bug

一开始是往响应链条那方面想的,搞了这坨代码测试

发现并不是什么响应链导致的

在网上搜了半天,也没有搜出个什么结果,然后思考了半天,也没有太好的思路,只好求助群友

忽然之前同事丢了这样一张截图

然后问他要了文档链接,但是**官方文档似乎已经更新了,我并没有找到上面截图的原文内容,他给了我一篇博客的链接**

有了这个思路,那我就想着把UIButton所有方法都打上断点,我单步调试一下,总能发现线索

UIButton所有方法设置断点命令

br set -r '\[UIButton .*\]$'

关于lldb调试命令的我不赘述了,后面贴出lldb调试学习链接

得到了如下结果

UIButton部分方法

这里由于UIButton所有方法实在太多了(总共311个),没办法全部截图,我只截取了其中导致这个bug的关键方法,见图片高亮方法

UIControl所有方法设置断点命令

br set -r '\[UIControl .*\]$'

UIControl全部方法

这两张图可以很清楚的看到,UIControl中没有这个方法[UIButton gestureRecognizerShouldBegin:]

那估计就是它了,随后我又给这个方法下了一个断点

br set -F "-[UIButton gestureRecognizerShouldBegin:]"

得到了这样的结果

可以清楚的看到[UIGestureRecognizer _shouldBegin]里面调用了[UIButton gestureRecognizerShouldBegin:]

然后再请看

到这里,整个bug导致的原因已经很清晰了

主要原因就是UIButton中的这个方法[UIButton gestureRecognizerShouldBegin:]

通过这次bug,也更新了自己对UIButtonUIControl的认知

非常感谢群友前同事的帮助的帮助,提供了一个很好的方向

测试Demo

参考链接