zoukankan      html  css  js  c++  java
  • IOS小技巧–用runtime 解决UIButton 重复点击问题

    IOS小技巧–用runtime 解决UIButton 重复点击问题

    什么是这个问题

    我们的按钮是点击一次响应一次, 即使频繁的点击也不会出问题, 可是某些场景下还偏偏就是会出问题.

    通常是如何解决

    我们通常会在按钮点击的时候设置这个按钮不可点击. 等待0.xS的延时后,在设置回来; 或者在操作结束的时候设置可以点击.

    - (IBAction)clickBtn1:(UIbutton *)sender
    {
        sender.enabled = NO;
        doSomething
        sender.enabled = YES;
    }

    如果涉及到按钮不同状态不同样式的时候, 用enabled不见得够用.还得额外加个变量来记录状态.

    - (IBAction)clickBtn1:(UIbutton *)sender
    {
        if (doingSomeThing) return;
    
        doingSomeThing = YES;
        doSomething
        doingSomeThing = NO;
    }

    笔者举的例子是直接在响应事件的周期内直接禁止点击的. 如果想做1秒内禁止重复点击的话,则得用performSelector:withObject:afterDelay:

    漂亮的解决是怎样的

    有了重复的代码段就是有了一个共性, 就可以抽象出来.

    我们可以给按钮添加一个属性重复点击间隔, 通过设置这个属性来控制再次接受点击事件的时间间隔.

    @interface UIControl (XY)
    @property (nonatomic, assign) NSTimeInterval uxy_acceptEventInterval;   // 可以用这个给重复点击加间隔
    @end
    
    static const char *UIControl_acceptEventInterval = "UIControl_acceptEventInterval";
    - (NSTimeInterval)uxy_acceptEventInterval
    {
        return [objc_getAssociatedObject(self, UIControl_acceptEventInterval) doubleValue];
    }
    
    - (void)setUxy_acceptEventInterval:(NSTimeInterval)uxy_acceptEventInterval
    {
        objc_setAssociatedObject(self, UIControl_acceptEventInterval, @(uxy_acceptEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }

    在app启动的时候,我们hook 所有的按钮的 event

    @implementation UIControl (XY)
    
    + (void)load
    {
        Method a = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));
        Method b = class_getInstanceMethod(self, @selector(__uxy_sendAction:to:forEvent:));
        method_exchangeImplementations(a, b);
    }
    
    @end

    在我们的点击事件里呢,对点击事件做下过滤

    - (void)__uxy_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event
    {
        if (NSDate.date.timeIntervalSince1970 - self.uxy_acceptedEventTime < self.uxy_acceptEventInterval) return;
    
        if (self.uxy_acceptEventInterval > 0)
        {
            self.uxy_acceptedEventTime = NSDate.date.timeIntervalSince1970;
        }
    
        [self __uxy_sendAction:action to:target forEvent:event];
    }

    实际使用起来就是这个样子

        UIButton *tempBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        [tempBtn addTarget:self action:@selector(clickWithInterval:) forControlEvents:UIControlEventTouchUpInside];
        tempBtn.uxy_acceptEventInterval = 0.5;



    文章至此就结束了.虽然不推荐大范围用runtime, 但是小范围内使用还是可以解决不少小问题的.

  • 相关阅读:
    LeetCode(287)Find the Duplicate Number
    LeetCode(290) Word Pattern
    LeetCode(205)Isomorphic Strings
    LeetCode(201) Bitwise AND of Numbers Range
    LeetCode(200) Number of Islands
    LeetCode(220) Contains Duplicate III
    LeetCode(219) Contains Duplicate II
    命令行执行Qt程序
    LeetCode(228) Summary Ranges
    redis 的安装和使用记录
  • 原文地址:https://www.cnblogs.com/wangxiaorui/p/5430006.html
Copyright © 2011-2022 走看看