首页 > 其他分享 >iOS 解决按钮防重复点击的问题

iOS 解决按钮防重复点击的问题

时间:2023-03-29 19:56:12浏览次数:57  
标签:iOS OBJC class 点击 按钮 method ASSOCIATION

日常使用中经常会出现按钮重复点击导致的数据重复提交问题,从而导致数据出错,常用的解决办法有
1、在发起请求的时候来一个全屏的loading这样在loading期间按钮就无法被点击,这种方式有个弊端就是loading弹窗起来需要几百毫秒时间左右,在这段时间期间用户如果手速过快,仍然可以触发多次点击事件;
2、发起提交时把按钮enabled或者userInteractionEnabled设置为false,然后提交完成或者返回错误时再把数据恢复,这种方法需要时刻记住按钮的使能状态,如果接口调用业务比较复杂,可能会导致某个场景未设置使能状态,从而导致按钮无法点击的情况;
3、按钮点击后存一下点击时间,按钮再次点击时把当前时间和上次时间比较,做一个时间差的换算,这样也确实可以解决问题,但是呢,每次都要去存时间和取时间在算时间,多少有点麻烦了,当然可以把这个功能写成一个分类来实现,该方法确实能解决问题,也是目前很多人都在使用的方案;
4、使用cancelPreviousPerformRequestsWithTarget:和performSelector来实现,通过该方法可以实现在指定时间范围内,如果重复点击,只会执行一次,本例中将使用该方案实现,当然该方案也有一定的弊端,就是永远只有最后一次按钮点击会被执行,这样就可能导致从按钮点击到触发事件可能会有时间延迟,本着学习的态度,探索一下performSelector的底层实现,本例采用该方案。

1、创建UIButton分类,并给分类添加属性interval,通过objc_setAssociatedObject和objc_getAssociatedObject来存储成员变量,该值用来做多次点击时间间隔,默认为0,interval为0的情况下走默认按钮点击事件,不处理多次点击事件

-(void)setInterval:(NSTimeInterval)interval{
    objc_setAssociatedObject(self, &kIntervalkey, @(interval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(NSTimeInterval)interval{
    NSNumber *number = objc_getAssociatedObject(self, &kIntervalkey);
    return number.doubleValue;
}

相关参数介绍:
key:要保证全局唯一,key与关联的对象是一一对应关系。必须全局唯一。
value:要关联的对象。
policy:关联策略。有五种关联策略。
OBJC_ASSOCIATION_ASSIGN 等价于 @property(assign)。
OBJC_ASSOCIATION_RETAIN_NONATOMIC等价于 @property(strong, nonatomic)。
OBJC_ASSOCIATION_COPY_NONATOMIC等价于@property(copy, nonatomic)。
OBJC_ASSOCIATION_RETAIN等价于@property(strong,atomic)。
OBJC_ASSOCIATION_COPY等价于@property(copy, atomic)。

2、重写+load方法,通过runtime交换UIButton的sendAction:to:forEvent:事件,UIButton的addTarget事件最终都会走这个方法

+(void)load{
    Class class = [self class];

    SEL originalSelector = @selector(sendAction:to:forEvent:);
    SEL swizzledSelector = @selector(swizzled_sendAction:to:forEvent:);
    
    Method originalMethod = class_getInstanceMethod(class, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
    
    BOOL success = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
    if (success) {
        class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}

注意 这里一定要先class_addMethod再执行交换操作,否则可能会导致[super class]调用交换方法时导致找不到方法crash
详细比较class_addMethod/class_replaceMethod/method_exchangeImplementations以及对应的区分和示例,可以查看该作者分享的内容,讲解的特别好,并且有详细的例子分析

https://www.jianshu.com/p/ccb75e5277b7

标签:iOS,OBJC,class,点击,按钮,method,ASSOCIATION
From: https://www.cnblogs.com/qqcc1388/p/17270132.html

相关文章

  • 在使用HOperatorSet.Draw忘记点击右键结束方法无法关闭窗体问题如果规避
      原文作者:aircraft原文链接:https://www.cnblogs.com/DOMLX/p/17266405.html 可以在离开窗体或者关闭窗体事件中调用HOperatorSet.HIOCancelDraw()方法进......
  • ios手机上 使用原生input出现的问题
       1、inputtextarea有阴影//兼容性样式:苹果手机input输入框和textarea都会有阴影。并且聚焦的时候会放大input,textarea{-webkit-appearance:none......
  • 点击图片标记红点
    /**获取图片的xy坐标【点击】*/getMouseXY(e){console.log('dadada')//offset是点击当前对象【这里点击img】的偏移量this.imgX=......
  • 使用原生input实现单选按钮组
    typeRadioType={bottomHeight?:number;name:string;label:string;dirNameList:string[];required?:boolean;onChange?:(value:string)=>vo......
  • iOS PCMAudio 与 g711a/g711u 的互转码
    iOSG711编码G.711是一种由国际电信联盟(ITU-T)制定的音频编码方式,又称为ITU-TG.711。它是国际电信联盟ITU-T定制出来的一套语音压缩标准,它代表了对数PCM(logarithmicp......
  • iOS 深色模式适配
    要求:iOS13.0以上重点:需要所有界面进行适配,工作量巨大,需要从项目开始就进行适配;H5界面无法进行适配 实现方式:SystemColors(常用)、SemanticColors(常用)、DynamicColors(......
  • Android开发-Android常用组件-Button按钮
    4.3 Button(按钮)Button控件继承TextView,拥有TextView的属性。StateListDrawable简介StateListDrawable是Drawable资源的一种,可以根据不同的状态,设置不同的图片......
  • Airtest新增iOS、Windows录屏功能,真香!
    1.前言在录屏这块,Airtest之前一直仅支持了Android设备,但Airtest1.2.9的新版录屏功能里,新增了iOS和Windows的录屏支持。下文我们将详细了解这个新的录屏功能,以及实操下在......
  • iOS自动打包 Swift Package 报错记录
      使用脚本自动打包iOSipa时,如果三方库有更新,swiftpakege加载库时报错,多半是git账号信息问题,钥匙串访问问题,尤其是有私有库存在时报错信息:1.errSecInternalComponen......
  • 直播平台源代码,iOS中使用 Date/NSDate 来获取时间
    直播平台源代码,iOS中使用Date/NSDate来获取时间将Date转为字符串类型extensionDate{  ///将Date转化为固定格式的字符串  ///-parameterformatter:时间......