zoukankan      html  css  js  c++  java
  • iOS 按钮连点问题

    在开发过程中应该都遇到这样的问题,当重复点击某个按钮时造成了push多次,造成体验很差,特别是在需要进行网络请求,网速不好时,出现的几率很大。这里主要介绍两种处理方式。

    1.点击一次后将button的可交互性变为NO

    如果在button的点击事件中要做耗时操作,比如进行网路请求时,可以考虑在点击时将按钮的可交互性变为NO,

    btn.userInteractionEnabled = NO

    然后在网络请求结束后再将其可交互性变为YES即可。这样可以有效避免按钮重复点击造成的多次puch问题,处理简单,缺点为比较麻烦,每个地方都要写,如果不加注意便会漏掉恢复可交互性。

    2.也就是网上最常用的解决方法,使用runtime控制button响应事件的时间间隔,使其规定时间内只响应一次点击事件。

    代码如下:

    button分类的.h文件

    @interface UIButton (Category)

    /** 按钮重复点击的时间间隔,以秒为单位 **/

    @property NSTimeInterval repeatEventInterval;

    @end

    .m文件

    #import <objc/message.h>

    // 默认的按钮点击时间间隔

    static const NSTimeInterval defaultDuration = 2.0f;

    const char *repeatEventIntervalKey  = "repeatEventIntervalKey";

    const char *previousClickTimeKey      = "previousClickTimeKey";

    @implementation UIButton (Category)

    + (void)load {

        

        // 交换方法实现

        Method sendAction = class_getInstanceMethod([self class], @selector(sendAction:to:forEvent:));

        Method xy_SendAction = class_getInstanceMethod([self class], @selector(xy_sendAction:to:forEvent:));

        

        method_exchangeImplementations(sendAction, xy_SendAction);

    }

    // // 重写,为了防止在tabBarController下点击tabBarItem时报错

    - (void)sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {

        [super sendAction:action to:target forEvent:event];

    }

    - (void)setRepeatEventInterval:(NSTimeInterval)repeatEventInterval {

        

        objc_setAssociatedObject(self, repeatEventIntervalKey, @(repeatEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    }

    - (NSTimeInterval)repeatEventInterval {

        

        NSTimeInterval repeatEventIn = (NSTimeInterval)[objc_getAssociatedObject(self, repeatEventIntervalKey) doubleValue];

        

        // 如果外界设置的重复点击的时间间隔大于0,就按照用户设置的去处理,如果用户设置的间隔时间小于或等于0,就按照无间隔处理

        if (repeatEventIn > 0) {

            return repeatEventIn;

        }else

        {

            return defaultDuration;

        }

        

        return 0.0;

    }

    - (void)setPreviousClickTime:(NSTimeInterval)previousClickTime {

        

        objc_setAssociatedObject(self, previousClickTimeKey, @(previousClickTime), OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    }

    - (NSTimeInterval)previousClickTime {

        

        NSTimeInterval previousEventTime = [objc_getAssociatedObject(self, previousClickTimeKey) doubleValue];

        if (previousEventTime != 0) {

            

            return previousEventTime;

        }

        

        return 1.0;

    }

    - (void)xy_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {

        

        NSTimeInterval time = [[[NSDate alloc] init] timeIntervalSince1970];

        if (time - self.previousClickTime < self.repeatEventInterval) {

            return;

        }

        

        // 如果间隔时间大于0

        if (self.repeatEventInterval > 0) {

            self.previousClickTime = [[[NSDate alloc] init] timeIntervalSince1970];

        }

        // 已在load中与系统的sendAction:to:forEvent:方法交换方法实现,所以下面调用的还是系统的方法

        [self xy_sendAction:action to:target forEvent:event];

    }

    @end

    参考链接:https://www.jianshu.com/p/98367b4d9816

  • 相关阅读:
    Javascript异步与同步问题
    promise解决异步问题:.then和async_await的渊源
    vue 爬坑之路----移动端适配rem单位
    vue 爬坑之路---can't resolve 'sass-loader'
    vue-cli新建vue项目
    sublimeT3编译sass.为css到指定的路径。
    禁止滚动条滚动
    让本地的静态html页面在node上跑起来
    地址三联动,简明实现
    关于数组去重
  • 原文地址:https://www.cnblogs.com/cui-cui/p/9890876.html
Copyright © 2011-2022 走看看