原有, 寫了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