前言
UIKit框架下点击或拖动事件的Target-Action设计模式
Target-Action,也叫“目标-动作”模式,即当某个事件发生的时候,调用特定对象的特定方法。“特定对象”就是Target,“特定方法”就是Action。
Target-Action模式主要包含两个部分:
- Target(对象):接收消息的对象。
- Action(方法):用于表示需要调用的方法。
- (void)addTarget:(nullable id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;
1、iOS代码触发button的点击事件2、快速找到按钮action
iOS问题分析方法之【 打印视图布局、符号调试、iOS逆向分析方法(快速找到按钮action、截获分析网络数据包、砸壳)】
I 控件是如何找到Target并执行对应的Action的?
- (void)sendAction:(SEL)action to:(nullable id)target forEvent:(nullable UIEvent *)event;
用户操作控件(比如点击)时,首先会调用这个方法,并将事件转发给应用程序的UIApplication对象。同时,在UIApplication类中也有一个类似的实例方法:
- (BOOL)sendAction:(SEL)action to:(nullable id)target from:(nullable id)sender forEvent:(nullable UIEvent *)event;
如果Target不为nil,应用程序会让该对象调用对应的方法响应事件;如果Target为nil,应用程序会在响应链中搜索定义了该方法的对象,然后执行该方法。
II 应用案例1:实现$AppClick事件的全埋点
2.1 方案
方案一:【以通过Method Swizzling交换UIApplication类中的-sendAction:to:from:forEvent:方法,然后在交换后的方法中触发AppClick事件,并根据target和sender采集相关属性,实现AppClick事件的全埋点。】
方案二:【实现AppClick事件的全埋点】(Method Swizzling交换UIView的-didMoveToSuperview方法给控件添加Target-Action并采集相关属性)
2.2 小结
方案一和方案二其实都运用了iOS中的Target-Action模式,这两种方案各有优劣。
对于方案一:
如果给一个控件添加了多个Target-Action,会导致多次触发$AppClick事件。
对于方案二:
由于SDK为控件添加了一个默认触发类型的Action,因此,如果开发者在开发过程中使用UIControl类的allTargets或者allControlEvents属性进行逻辑判断,有可能会引入一些无法预料的问题。
III 应用案例2:逆向分析
- iOS 使用代码触发button的点击事件:【 [btn sendActionsForControlEvents:UIControlEventTouchUpInside];】及教你找到按钮action
1、iOS代码触发button的点击事件2、快速找到按钮action
iOS问题分析方法之【 打印视图布局、符号调试、iOS逆向分析方法(快速找到按钮action、截获分析网络数据包、砸壳)】
IV 应用案例3:限制按钮的点击频率
文章地址:https://kunnan.blog.csdn.net/article/details/117352527
在项目开发中,会对数据库数据进行更新操作的接口请求,不仅服务器侧需要控制请求频率以及保证数据的唯一性和一致性,app侧也需要进行限制来避免测试垃圾数据
原理:利用runtime API 对UIButton方法sendAction:to:forEvent:进行方法实现的交换,来控制事件的响应频率
SEL selA = @selector(sendAction:to:forEvent:);
V、知识储备:什么是响应者链?
iOS触摸事件:什么是响应者链?
see also
- iOS 使用代码触发button的点击事件:【 [btn sendActionsForControlEvents:UIControlEventTouchUpInside];】及教你找到按钮action