標籤:
在項目開發中我們可能會遇到這樣子的情況,比如在我們登陸的時候需要把資料發送給伺服器進行比對,通常我們的做法是當使用者點擊按鈕後,使用一個載入效果的view遮擋住當前介面,直到伺服器返回資料或者逾時。如果不進行遮擋,使用者可能頻繁的點擊登入,而你又一直發送資料,這樣子顯然是不信的,解決這樣子的方法有很多種。
今天我們說一種方式,讓按鈕回應時間由自己控制。
要想達到這種效果你可能需要去瞭解一下什麼是 Runtime
OK,如果你不是很瞭解也沒有關係,對於這個功能用到的也不多。其中包括:
1 objc_getAssociatedObject(<#id object#>, <#const void *key#>) 2 參數一:一般都是self,調用者 3 參數二:你的key(key - value) 4 5 6 有get方法那麼肯定會有set 7 8 objc_setAssociatedObject(<#id object#>, <#const void *key#>, <#id value#>, <#objc_AssociationPolicy policy#>) 9 參數一:self10 參數二:key11 參數三:value,這裡要注意封裝成為id類型對於int、float等基本類型12 參數四:MRC基礎的東西13 /*14 OBJC_ASSOCIATION_ASSIGN = 0, 15 OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, 16 OBJC_ASSOCIATION_COPY_NONATOMIC = 3, 17 OBJC_ASSOCIATION_RETAIN = 01401, 18 OBJC_ASSOCIATION_COPY = 0140319 */20 為什麼會用到上面的方法,因為在給一個Category動態添加屬性。
完成了動態添加屬性之後,我們需要利用Runtime的性質去對系統的方法動動手腳了。
這裡我們還需要瞭解三個方法 分別是:
通過這個方法可以得到系統對象方法的編號,類型是Methodclass_getInstanceMethod(<#__unsafe_unretained Class cls#>, <#SEL name#>)通過這個方法可以擷取到系統類別方法的編號,類型是Methodclass_getClassMethod(<#__unsafe_unretained Class cls#>, <#SEL name#>)這裡我們要擷取到的是對象的方法,所以用第一個,在擷取到系統的方法之後呢,我們需要定義一個自己的方法,用來和系統的方法進行互換互換兩個方法的編號method_exchangeImplementations(<#Method m1#>, <#Method m2#>):互換前和互換後交換前
交換後
所以我就達到了交換的目的。
瞭解了上面的幾個方法之後,我們就可以開始 寫代碼了
首先如果想要使用Runtime第一步你得先匯入:
#import <objc/message.h>
第二步利用Runtime動態去添加屬性
這裡要重寫get set方法。
通過kvc賦值,所以我們先要有key,用來存/取資料
static char * const PQ_ACCEPTTIMEKEY = "pq_acceptTime";static char * const PQ_DELAYINTERVALKEY = "pq_delayButtonInterVal";// getter method- (NSTimeInterval)pq_delayButtonInterVal{return [objc_getAssociatedObject(self, PQ_DELAYINTERVALKEY) doubleValue];}- (NSTimeInterval)pq_acceptTime{return [objc_getAssociatedObject(self, PQ_ACCEPTTIMEKEY) doubleValue];}// setter method- (void)setPq_delayButtonInterVal:(NSTimeInterval)pq_delayButtonInterVal{objc_setAssociatedObject(self, PQ_DELAYINTERVALKEY, @(pq_delayButtonInterVal), OBJC_ASSOCIATION_RETAIN_NONATOMIC);}- (void)setPq_acceptTime:(NSTimeInterval)pq_acceptTime{objc_setAssociatedObject(self, PQ_ACCEPTTIMEKEY, @(pq_acceptTime), OBJC_ASSOCIATION_RETAIN_NONATOMIC);}
完成動態添加屬性之後,我們要把系統的方法和我們的方法進行互換,以便於添加功能。
1 + (void)load{ 2 static dispatch_once_t onceToken; 3 dispatch_once(&onceToken, ^{ 4 Method systemMethod = class_getInstanceMethod([self class], @selector(sendAction:to:forEvent:)); 5 Method myselfMethod = class_getInstanceMethod([self class], @selector(pq_sendAction:to:forEvent:)); 6 BOOL isAdd = class_addMethod([self class], @selector(sendAction:to:forEvent:), method_getImplementation(myselfMethod), method_getTypeEncoding(myselfMethod)); 7 if (!isAdd) { 8 method_exchangeImplementations(systemMethod, myselfMethod); 9 }10 });11 }
然後我們就要寫自己的方法了,這裡有一個小技巧把,先把系統的方法名打上,比如對於這個方法可以這樣做:
1. 先輸入 - sendAction 一般打到這裡系統就會提示自動補全
2. 得到系統的方法名之後在前面添加我們的首碼,表示是我們自己的方法。比如
這裡我就添加了一個首碼pq,再用底線串連。
- (void)pq_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event
接下來就是處理代碼的實現
1 這裡用到的兩個變數一個需要對外公開(.h檔案中),一個寫在(.m檔案中的) 2 @interface UIControl () 3 4 @property (nonatomic,assign) NSTimeInterval pq_acceptTime; 5 6 @end 7 8 - (void)pq_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event{ 9 if (NSDate.date.timeIntervalSince1970 - self.pq_acceptTime < self.pq_delayButtonInterVal) {10 NSLog(@"現在點我我也不鳥你");11 return;12 }13 if (self.pq_delayButtonInterVal > 0) {14 self.pq_acceptTime = NSDate.date.timeIntervalSince1970;15 }16 [self pq_sendAction:action to:target forEvent:event];17 }
至此,功能就完成啦,小夥伴們可以馬上使用了
自己建立一個button,然後設定如下代碼,如果你發現找不到你自己定義的屬性,那麼你一般是沒有匯入標頭檔在ViewController中
//設定這個延時時間是5秒鐘
self.clickMeBtn.pq_delayButtonInterVal = 5;
到這裡就全部完成啦,碼字不容易,如果您覺得還行,麻煩頂一下!轉載請註明出處,謝謝。
IOS動態修改按鈕回應時間