Release模式下UIButton按鈕不可以二次點擊

原有, 寫了UIControl的分類, 防止重複點擊, 也是在網上copy了很多代碼, 之前測試都是跑的Debug版的, 沒有任何問題. 上線前跑了個Release版的自測一下, 發現神奇的一幕發生了. 所有UIButton的點擊方法只可以實現一次, 不可以跑第二次.

請教了朋友,找了1個多小時, 在朋友的提示下, 問我你是不是有防重. 纔想起來分類, 去看了看. 結果果然是這個問題.

第一種解決辦法把分類裏load方法交換註釋掉, 一切ok.

第二種解決辦法, 依舊保留方法交換,但是在分類裏自定義方法裏

//        [self performSelector:@selector(setEventUnavailable:) withObject:@(YES) afterDelay:self.emDuration];

修改爲

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.emDuration*NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

                self.eventUnavailable = NO;

            }); 先把問題解決掉了. 後來朋友我們幾個就開始討論爲什麼會有這種問題. 感謝https://www.coderzhou.com/2017/11/12/%E4%B8%80%E6%AC%A1%E7%94%B1performSelector%E5%BC%95%E5%8F%91%E7%9A%84BUG/ 這個作者的無私奉獻.  結合到自己的代碼發現是因爲Bool值self.eventUnavailable 導致的. performSelector:withObject:afterDelay 這個方法在release和debug下結果不一致

 

感興趣的同學可以參考這篇http://blog.zats.io/2014/03/12/performSelector-withObject/ 在32和64環境編譯下結果不一樣的

另外附上我的垃圾防重點分類. 希望對跟我一樣出問題的同學們有幫助. 代碼還是自己寫吧. 像我就是在網上找的防重點的方法, 網上基本都是這樣寫的. 出問題了還得自己解決

#import <UIKit/UIKit.h>

@interface UIControl (EMTimer)

// 重複點擊間隔

@property (nonatomic, assign) NSTimeInterval emDuration;

@end

 

實現

#import "UIControl+EMTimerl.h"

#import <objc/runtime.h>

static char * const emDuration = "emDurationKey";

static char * const eventUnavailableKey = "eventUnavailableKey";

@interface UIControl ()

@property (nonatomic, assign) BOOL eventUnavailable;

@end

@implementation UIControl (EMTimer)

+ (void)load {

    Method method = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));

    Method qi_method = class_getInstanceMethod(self, @selector(qi_sendAction:to:forEvent:));

    method_exchangeImplementations(method, qi_method);

}

#pragma mark - Action functions

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

    if (self.eventUnavailable == NO) {

        self.eventUnavailable = YES;

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

//        [self performSelector:@selector(setEventUnavailable:) withObject:@(YES) afterDelay:self.emDuration];

            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.emDuration*NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

                self.eventUnavailable = NO;

            });

    }

}

#pragma mark - Setter & Getter functions

- (NSTimeInterval)emDuration {    

    return [objc_getAssociatedObject(self, emDuration) doubleValue];

}

- (void)setEmDuration:(NSTimeInterval)qi_eventInterval {

    objc_setAssociatedObject(self, emDuration, @(qi_eventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);

}

- (BOOL)eventUnavailable {

    return [objc_getAssociatedObject(self, eventUnavailableKey) boolValue];

}

- (void)setEventUnavailable:(BOOL)eventUnavailable {    

    objc_setAssociatedObject(self, eventUnavailableKey, @(eventUnavailable), OBJC_ASSOCIATION_RETAIN_NONATOMIC);

}

@end

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章