背景
本文是修复了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,也更新了自己对UIButton
和UIControl
的认知