[iOS] 利用 runtime,解決多次點擊相同 button,導致重復跳轉的問題

ytd069qxa 9年前發布 | 13K 次閱讀 iOS開發 移動開發

場景

當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</code></pre>

在 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</code></pre>

擴展閱讀:

Objective-C Runtime Reference - Apple Developer

Objective C運行時(runtime)技術的幾個要點總結

OC運行時編程指南

Method Swizzling

 

來自:http://www.jianshu.com/p/65ce6471cd0f

 

Save

 本文由用戶 ytd069qxa 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!