要在Objective-C中建立一個高度可複用的工具類,以防止按鈕的暴力點選,並且使用切面程式設計(AOP)的方式,我們可以考慮使用Aspects
這個庫來實現方法的攔截。以下是具體的實現步驟:
第一步:引入Aspects庫
首先,需要將Aspects
整合到專案中。Aspects
是一個輕量級的AOP框架,允許你在執行時攔截類的例項方法和類方法。你可以透過CocoaPods來新增此庫:
pod 'Aspects'
第二步:建立UIButton的Category
接下來,建立一個UIButton的Category,用於新增防暴力點選的邏輯。
UIButton+PreventSpam.h:
#import <UIKit/UIKit.h>
@interface UIButton (PreventSpam)
// 設定間隔時間,進行防暴力點選設定
- (void)setPreventSpamInterval:(NSTimeInterval)interval;
@end
UIButton+PreventSpam.m:
#import "UIButton+PreventSpam.h"
#import <objc/runtime.h>
#import <Aspects/Aspects.h>
static const char *UIButton_preventSpamIntervalKey = "UIButton_preventSpamIntervalKey";
@implementation UIButton (PreventSpam)
- (void)setPreventSpamInterval:(NSTimeInterval)interval {
objc_setAssociatedObject(self, UIButton_preventSpamIntervalKey, @(interval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
// 使用Aspects進行方法攔截
[self aspect_hookSelector:@selector(sendAction:to:forEvent:) withOptions:AspectPositionInstead usingBlock:^(id<AspectInfo> aspectInfo, SEL action, id target, UIEvent *event) {
UIButton *button = aspectInfo.instance;
if (button.isIgnoring) {
return;
}
button.isIgnoring = YES;
// 執行原始的 sendAction:to:forEvent: 方法
// 這裡直接呼叫原始方法是不合適的,因為這是一個攔截後的block,我們要重新invoke original invocation
[[aspectInfo originalInvocation] invoke];
// 延遲間隔時間後,重置為可以點選
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(interval * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
button.isIgnoring = NO;
});
} error:NULL];
}
// 判斷當前是否應該忽略點選,透過關聯物件新增屬性
- (void)setIsIgnoring:(BOOL)isIgnoring {
objc_setAssociatedObject(self, @selector(isIgnoring), @(isIgnoring), OBJC_ASSOCIATION_ASSIGN);
}
- (BOOL)isIgnoring {
return [objc_getAssociatedObject(self, @selector(isIgnoring)) boolValue];
}
@end
使用
在適當的位置設定按鈕的點選間隔:
#import "UIButton+PreventSpam.h"
[myButton setPreventSpamInterval:1.0]; // 點選間隔設定為1秒
注意
-
本示例使用了
Aspects
庫進行方法的攔截,這是一種執行時AOP的技巧。這裡利用了Objective-C的動態特性。AOP可以幫助增加程式碼的可維護性和可複用性,但它也會增加程式碼的複雜性,使用時需要權衡。 -
使用關聯物件(
objc_setAssociatedObject
和objc_getAssociatedObject
)來給UIButton動態新增屬性,用於儲存是否應該忽略點選和間隔時間,這是Objective-C擴充套件現有類功能的常用技巧。 -
在實際專案中,可能需要考慮多種情況和細節,如處理快速切換介面時按鈕點選事件的響應等。