• 利用 runtime,解决多次点击相同 button,导致重复跳转的问题-b


    当app有点卡的时候,多次点击相同的button,经常出现,跳转了N次相同的界面(比如闲鱼)

    解决办法

    用运行时和分类,替换 UIControl 响应事件,根据响应的间隔时间来判断是否执行事件。

    详细步骤

    1. UIControl

      创建一个 UIControl 的分类

      Snip20160816_3.png

    Snip20160816_4.png

    为了方便他人调整不同的间隔时间需求,在 UIControl+Custom.h 文件中开放间隔时间属性, UIControl+Custom.h 文件的代码为:

    //  UIControl+Custom.h 
    //  Created by ocarol on 16/8/16. 
    //  Copyright © 2016年 ocarol. All rights reserved. 
    //  
    #import <UIKit/UIKit.h>  
    @interface UIControl (Custom) 
    @property (nonatomic, assign) NSTimeInterval custom_acceptEventInterval;// 可以用这个给重复点击加间隔 
    @end

    在 UIControl+Custom.m 文件中实现方法交换(妥善的做法是:先添加方法,如果方法已经存在,就替换原方法),在 UIControl+Custom.m 文件的代码为:

    //  UIControl+Custom.m
    //  Created by ocarol on 16/8/16.
    //  Copyright © 2016年 ocarol. All rights reserved.
    //
    #import "UIControl+custom.h"
    #import <objc/runtime.h>
    @interface UIControl()
    @property (nonatomic, assign) NSTimeInterval custom_acceptEventTime;
    @end
    @implementation UIControl (Custom)
    + (void)load{     
        Method systemMethod = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));     
        SEL sysSEL = @selector(sendAction:to:forEvent:);     
        Method customMethod = class_getInstanceMethod(self, @selector(custom_sendAction:to:forEvent:));     
        SEL customSEL = @selector(custom_sendAction:to:forEvent:);      
        //添加方法 语法:BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types) 若添加成功则返回No     
        // cls:被添加方法的类  name:被添加方法方法名  imp:被添加方法的实现函数  types:被添加方法的实现函数的返回值类型和参数类型的字符串     
        BOOL didAddMethod = class_addMethod(self, sysSEL, method_getImplementation(customMethod), method_getTypeEncoding(customMethod));      
        //如果系统中该方法已经存在了,则替换系统的方法  语法:IMP class_replaceMethod(Class cls, SEL name, IMP imp,const char *types)     
        if (didAddMethod) {         
            class_replaceMethod(self, customSEL, method_getImplementation(systemMethod), method_getTypeEncoding(systemMethod));     
        }else{         
            method_exchangeImplementations(systemMethod, customMethod);      
        }
    }
    - (NSTimeInterval )custom_acceptEventInterval{     
            return [objc_getAssociatedObject(self, "UIControl_acceptEventInterval") doubleValue];
    }
    - (void)setCustom_acceptEventInterval:(NSTimeInterval)custom_acceptEventInterval{     
        objc_setAssociatedObject(self, "UIControl_acceptEventInterval", @(custom_acceptEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    - (NSTimeInterval )custom_acceptEventTime{     
        return [objc_getAssociatedObject(self, "UIControl_acceptEventTime") doubleValue];
    }
    - (void)setCustom_acceptEventTime:(NSTimeInterval)custom_acceptEventTime{     
        objc_setAssociatedObject(self, "UIControl_acceptEventTime", @(custom_acceptEventTime), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    - (void)custom_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event{     
        // 如果想要设置统一的间隔时间,可以在此处加上以下几句    
        // 值得提醒一下:如果这里设置了统一的时间间隔,会影响UISwitch,如果想统一设置,又不想影响UISwitch,建议将UIControl分类,改成UIButton分类,实现方法是一样的    
        // if (self.custom_acceptEventInterval <= 0) {    
        //     // 如果没有自定义时间间隔,则默认为2秒    
        //    self.custom_acceptEventInterval = 2;    
        // }      
        // 是否小于设定的时间间隔     
        BOOL needSendAction = (NSDate.date.timeIntervalSince1970 - self.custom_acceptEventTime >= self.custom_acceptEventInterval);      
        // 更新上一次点击时间戳     
        if (self.custom_acceptEventInterval > 0) {         
            self.custom_acceptEventTime = NSDate.date.timeIntervalSince1970;     
        }      
        // 两次点击的时间间隔小于设定的时间间隔时,才执行响应事件     
        if (needSendAction) {         
            [self custom_sendAction:action to:target forEvent:event];     
        }   
    } 
    @end
  • 相关阅读:
    去除文件及子文件的隐藏和只读属性
    一个比较全的C++农历算法(转)
    Activity 的窗口去头的方式
    SQL查询显示行号、随机查询、取指定行数据
    C++中map用法详解(转)
    窗口消息大全(转)
    CTreeCtrl的用法汇总(转)
    CTreeView和CTreeCtrl的使用方法(转)
    用CImage加载内存里的Image(转)
    序列化编程,保存和读取配置文件
  • 原文地址:https://www.cnblogs.com/isItOk/p/5838212.html
Copyright © 2020-2023  润新知