iOS UIButton 偶现不响应问题

一. 问题背景

有同时反馈,评价弹框的匿名评价按钮,在他的手机上点击没有任何响应,但是在其他人的手机上面是正常的,因此进行排查。

二. 问题分析

经排查项目里面的代码对按钮的声明类似如下:

var testButton: UIButton = {
        let btn = UIButton()
        btn.setTitle("点击", for: .normal)
        btn.setTitleColor(.red, for: .normal)
        btn.addTarget(self, action: #selector(testButtonClicked), for: .touchUpInside)
        return btn
    }()

swfit声明UIButton变量,没有加上lazy,使得这个变量调用是在init构造方法之前,所以这里testButtontargetself,因为还没调用init方法,所以这里selfnil

之所以nil也没问题,是因为点击触摸到屏幕的时候,首先通过响应链找到第一响应者testButton,然后testButton将添加到自身点击事件发送给UIApplicationUIApplication判断如果targetnil,就会以第一响应者testButton为起点,沿着响应链去判断,响应链条上面的视图是否可以响应点击事件,如果可以响应,则将事件发送给该视图,触发selector,停止传递;

如果响应链上的视图都不能响应该事件,就直接抛弃这个响应事件,因此这里即使target传入了nil,沿着响应链去寻找方法响应者,刚好找到了FJFButtonTestView可以响应#selector(testButtonClicked),所以直接将事件传给FJFButtonTestView的去处理。

但在有问题的手机上,调试发现,因为testButton是写在FJFButtonTestView里面的,testButton响应的selector方法也是放在FJFButtonTestView里面,因为传入的targetnilUIApplication则直接将事件发送到UIViewController上,直接沿着UIViewController的响应链去传递,而不是从第一响应者的响应链开始传递,因此导致了,放到FJFButtonTestView上的点击事件压根不响应。

至于为什么在有问题手机系统上面,没有第一响应者testButton为起点,沿着响应链去查找是否可以响应该事件的响应者,而是直接从UIViewController开始查找,这个问题,我看官方文档是这样说的:

When adding an action method to a control, you specify both the action method and an object that defines that method to the addTarget(_:action:for:) method. (You can also configure the target and action of a control in Interface Builder.) The target object can be any object, but it’s typically the view controller’s root view that contains the control. If you specify nil for the target object, the control searches the responder chain for an object that defines the specified action method.
https://developer.apple.com/documentation/uikit/uicontrol

这里意思是说如果你的target传入为nil,那么UIControl将在响应链中搜索定义action的对象。文章并没有明确是从第一响应者沿着响应链去查找。

这是我当时拿到反馈问题手机调试的堆栈(是另一个OC版本的Demo):

origin_img_v2_b8f033f6-24ca-4537-8aff-ea70c34b079g.jpg

从堆栈可以很明显看出UIApplication直接将事件发送给FJFButtonClickedViewController上定义的- (void)testButtonClicked:(UIButton *)sender响应事件。

至于本质原因我也没找到,如果有了解的朋友,还请告知下。

三. 解决方案

方案一: 添加lazy声明为懒加载方式

// MARK: - Lazy
    lazy var testButton: UIButton = {
        let btn = UIButton()
        btn.setTitle("点击", for: .normal)
        btn.setTitleColor(.red, for: .normal)
        btn.addTarget(self, action: #selector(testButtonClicked), for: .touchUpInside)
        return btn
    }()

通过将变量声明为lazy,懒加载方式,等到View初始化完成之后,再去真正的调用。

方案二:将button声明为可选项,等到真正用到再去初始化

    private var testButton: UIButton?
    // MARK: - Life
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        setupViewControls()
        layoutViewControls()
    }
    // MARK: - Private
    private func setupViewControls() {
        let btn = UIButton()
        btn.setTitle("点击", for: .normal)
        btn.setTitleColor(.red, for: .normal)
        btn.addTarget(self, action: #selector(testButtonClicked), for: .touchUpInside)
        self.addSubview(btn)
        testButton = btn
    }

这两种方式都能保证,button添加targetself是有值的。

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

推荐阅读更多精彩内容

  • 本文主要讲解iOS触摸事件的一系列机制,涉及的问题大致包括: 触摸事件由触屏生成后如何传递到当前应用? 应用接收触...
    Leoeoo阅读 1,575评论 0 7
  • 参考文件:1.官方文档2.iOS触摸事件那点儿事3.iOS 点击事件传递及响应4.iOS事件处理,看我就够了 1....
    你weixiao的时候很美阅读 496评论 0 1
  • 作者:Lotheve链接:https://www.jianshu.com/p/c294d1bd963d[https...
    寻心_0a46阅读 665评论 0 2
  • 好奇触摸事件是如何从屏幕转移到APP内的?困惑于Cell怎么突然不能点击了?纠结于如何实现这个奇葩响应需求?亦或是...
    Lotheve阅读 54,734评论 51 596
  • 本文主要讲解iOS触摸事件的一系列机制,涉及的问题大致包括: 触摸事件由触屏生成后如何传递到当前应用? 应用接收触...
    baihualinxin阅读 1,160评论 0 9