標籤:
早期我們使用延時執行的方法都是用NSObject 類提供的,performSelector:系列的方法,具體有哪些我們看一下
我們一般讓某個對象延時執行某個方法都會調用包含 afterDelay這個參數的方法,此參數即代表延時多長時間執行 ,但是這一系列的方法的參數都只接受繼承自NSObject類得對象,也就是說如果我們要向其中傳入基本的資料類型,那就必須涉及到資料類型轉換,這顯然會增加開銷,而且這一系列的方法最多也就能傳如一個參數,如果我們要傳多個參數怎麼辦呢 ,如果想繼續使用這個方法,那我們就必須把多個參數寫入數組或字典中去,然後把數組或字典對象傳給這個方法,那麼著就又會增加我們插入數組或字典,解析數組或字典的代碼 ,資料量達到一定情況的話,這個開銷是可想而知的,而且我們還要知道數組和字典中得每個對象都代表什麼,很麻煩;
不過我們可以用塊來解決這一問題 ,GCD 為我們提供了一個示範執行的塊函數,其具體定義如下:
void dispatch_after ( dispatch_time_t when, dispatch_queue_t queue, dispatch_block_t block );
我們在調用此方法的時候,系統也考慮的很周到,當我們寫入dispatch_after時,這個完整的函數就會呈現出來,我們看一下
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ });
調用很方便,如果我們想把裡面的內容放到主線程中去啟動並執行話,也很方便,例如:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{ [son study]; });});
還記得當時有一個問題,就是想給UIButton的點擊事件加點料,讓系統中的所有的按鈕都禁止快速點擊或者連擊,當時問了看了好多部落格,都沒有好的解決方案,前篇一律的討論或者建議,都是使用performSelector:afterDelay這種方法,但是這樣的話,我還要實現另一個方法 。後來是這麼解決的呢 ,這裡再次引用我之前寫的內容,重寫父類函數,然後使用GCD的dispatch_after 方法解決;
具體實現如下:
//// CommonButton.h// CommonButton//// Created by pk on 14/12/24.// Copyright (c) 2014年 pk. All rights reserved.//#import <UIKit/UIKit.h>@interface CommonButton : UIButton@end
//// CommonButton.m// CommonButton//// Created by pk on 14/12/24.// Copyright (c) 2014年 pk. All rights reserved.//#import "CommonButton.h"@implementation CommonButton/*// Only override drawRect: if you perform custom drawing.// An empty implementation adversely affects performance during animation.- (void)drawRect:(CGRect)rect { // Drawing code}*/- (void)sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event{ [super sendAction:action to:target forEvent:event]; self.enabled = NO; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.enabled = YES; });}@end
這樣的實現,很清楚,結構簡明,使用簡單,想使用此方法,只要將改一下類得繼承就行;
總結:performSelector 系列方法所能處理的選取器太過於局限性了 ,選取器的傳回值類型和參數的個數都會受到限制;
而dispatch_after就沒有這些問題,另外,如果想把任務放在另一個線程上執行,最好不要用performSelector系列方法,而應該把任務封裝到塊裡,然後調用GCD的相關方法來實現就行
iOS 高效開發-----延時執行用GCD