调用系统相机,点击拍照, 发现只能长按才可以,点击无响应。

问题描述:
调用系统相机,点击拍照, 发现只能长按才可以,点击无响应。

排查的结果是:
重写了一个button 的类别 ,导致拍照时的Button事件出现问题

结论:
在项目中谨慎为系统类添加分类

如下作者做了很详细的说明:
1、坚决杜绝为系统类做方法交换(见到【class_replaceMethod】格杀勿论!)

2、为系统类添加分类时候,属性和方法名必须加上【世上独一无二】的前缀,避免冲突和混淆。
之所以让我对上述行为恨之入骨是因为,今天为了一个bug,我花了将近半天时间苦苦追寻原因。

我只是使用了一个简简单单的UIImagePickerController的拍照的功能界面,奇葩的现象是,点击快门按钮时---可以看见界面中的按钮发生了视觉上的响应,但是却没有功能上的响应(按道理,我这边按下按钮的时候,拍照就会完成输出图片数据)。

我的整个思考过程是这样的:

点击没功能反应?难道有谁把这个类中的响应方法重写了?

---寻找UIImagePickerController在整个项目中的出现,看有没有对它做分类,或者是子类化。结果是没有的!

那是不是关于UIImagePickerController这个类,随着iOS的SDK的更新,我有些属性或者方法需要适配下?

---我用iOS10.2和iOS11.2和最新的iOS11.4都看了一遍,都有这个问题。难道从iOS10开始就要有些跟之前不一样的适配需要做?我翻看相关的适配博客,没有发现!

难道是我对事件响应链做了一些调整?导致事件被阻断?

---我回头看了一眼UIImagePickerController对象创建后使用的是模态出来的,一个简单的展示链,没有问题!

难道多线程问题?

---NONONO!我核对了下代码,整个过程都在主线程中,至于就算UIImagePickerController里面的处理上开了子线程,那也不归我们管,它暴露出来的API肯定是在主线程的。

那就见鬼了~但是,不对啊,就这个简单的UIImagePickerController,不至于啊!

---我应该是知道肯定是项目中的其他SDK的环境影响到了它,但是会是什么呢?为了更加确定我的这个想法,给自己继续追寻原因的信心,我新建demo,这块代码原样放入。卧槽,完美运行。

那行,我这样的话,我要一查到底!

---能够引起这个问题的全局原因,那么就是项目的配置数据有误,那么就是分类的原因。

项目的配置数据就是那些,最多就是在info文件中说明下使用相机的原因,方便获取用户的授权。因此我肯定,这块没有问题。

分类的话,我已经确定了没有UIImagePickerController的分类。那么肯定就是其他系统类的分类了。

首先,添加分类的不可控性体现在:

(1)如果在分类中重写类的方法,分类的重写优先级是最高的。

(2)如果系统对UIImagePickerController添加了一些分类(包括不暴露在API中的),刚好又与项目中对其的分类方法名重复,会后入为主的。

(3)另外分类是会在编译器就全部加上的,如果在分类中对类本身做的处理是会影响到类本身的。也就是说,如果对类中的方法做了方法转移的处理,那就无形中影响了。

于是我赶紧搜索方法转移的class_replaceMethod方法名有没有在项目中出现。果然,项目中对UIButton的分类中重写了+load类方法,在改方法中做了方法转移!

正如前面分析的,重写+load方法的优先级:分类中>子类中>类本身。

并且重写的是+load这个方法,完全可以做到悄无声息。

为了进一步验证就是这个原因,我直接将这个分类的实现方法注释掉,然后运行项目~【method_exchangeImplementations完美运作!!】

刚刚时候的是相当于反编译的方式把问题的根源找到了,现在我需要的是使用顺推的方法,把问题的出现原因梳理清楚。

通过查看UIButton的这个分类知道,它是将@selector(sendAction:to:forevent:)这个方法替换掉了。sendAction:to:forevent:方法中实际调用的是objc_setAssociatedObject,替换后的方法,在其中加了一个计时器,使得规定时间内,只能objc_setAssociatedObject调用一次。

这样的做法,应该是为了防止button高频按动而做的改动。

然而,UIImagePickerController功能界面中的快门按钮,实际上是在拍照功能时,按住快门键不放,可以实现高频连拍的功能(我试了下最多时999张),这样的话,就很好解释通了。虽然,按住快门键按钮不放是一个“长按”手势,但是其内部的实现肯定是高频的调用@selector(sendAction:to:forevent:)这个方法。说到这里,我得说明下,虽然长按手势和单点手势表面上的确是不一样的,但是其内部都调用了@selector(sendAction:to:forevent:)这个方法。因此,之前写button这个分类的目的虽然是防止用户高频的单击按钮,但是现在用户虽然不是高频的单击,而是长按,但是都调用的是@selector(sendAction:to:forevent:)这个方法。毕竟,当初为了防止用户高频单击,是替换掉了@selector(sendAction:to:forevent:)这个方法。因此,谜底揭开了,整个离奇的故事真相大白~

,也可以附上我的文章出处:http://www.cnblogs.com/cchHers/

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,904评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,581评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,527评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,463评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,546评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,572评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,582评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,330评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,776评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,087评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,257评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,923评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,571评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,192评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,436评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,145评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容