【iOS沉思錄】iOS中如何觸發定時任務或延時任務?
阿新 • • 發佈:2019-01-01
iOS中如何觸發定時任務或延時任務?
定時任務指的是週期性的呼叫某個方法,實現任務的反覆執行,例如倒計時功能的實現;延時任務指的是等待一定時間後再執行某個任務,例如頁面的延時跳轉等。iOS中控制任務的延時或定時執行的方法有很多,使用中要注意是同步還是非同步,是否會阻塞主執行緒等問題。實現方法主要如下:
1.performSelector實現延時任務
延時任務可以通過當前UIViewController的performSelector隱式建立子執行緒實現,不會阻塞主執行緒:
/* 延遲10s執行任務 */
[self performSelector:@selector(task) withObject:nil afterDelay:10];
-(void)task
{
// delay task
}
2.利用sleep實現後面任務的等待,慎用,會阻塞主執行緒
NSThread sleepForTimeInterval:10.0];
3.GCD實現延時或定時任務
通過GCD實現block程式碼塊的延時執行:
dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC);
dispatch_after(delay, dispatch_get_main_queue(), ^{
// delay task
});
GCD也可以用來定義計時器實現定時器功能,可以設定延時開啟計時器,使用中要注意一定要定義強指標指向計時器物件才可讓計時器生效:
/* 必須要用強指標指引計時器才會生效 */
@property (nonatomic, strong)dispatch_source_t timer;
/* 在指定執行緒上定義計時器 */
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0 , 0, queue);
/* 開始的時間 */
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC));
/* 設定計時器 */
dispatch_source_set_timer(_timer, when, 1.0 * NSEC_PER_SEC, 0);
/* 計時器回撥block */
dispatch_source_set_event_handler(_timer, ^{
NSLog(@"dispatch_source_set_timer is working!");
});
/* 開啟計時器 */
dispatch_resume(_timer);
/* 強引用計時器物件 */
self.timer = _timer;
4.NSTimer實現定時任務
5.CADisplayLink實現定時任務
CADisplayLink實現的定時器與螢幕重新整理頻率繫結在一起,是一種幀率重新整理,適用於介面的不斷重繪(例如流暢動畫和視訊播放等)。CADisplayLink以特定模式註冊到runloop後,每當螢幕顯示內容重新整理結束就會向CADisplayLink指定的target傳送一次訊息,實現target的每幀呼叫。根據需求也可以設定每幾幀呼叫一次,預設每幀都呼叫。另外通過CADisplayLink還可以獲取幀率和時間等資訊。
CADisplayLink實現方法的每幀呼叫使其計時精度非常高,但如果呼叫的方法十分耗時,超過一幀的時間間隔,會導致跳幀,跳幀次數取決於CPU的忙碌程度。
- (void)viewDidLoad {
[super viewDidLoad];
CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLink_SEL)];
/* 新增到當前執行的RunLoop中啟動 */
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
/* 暫停、繼續對selector的呼叫 */
//[displayLink setPaused:YES];
//[displayLink setPaused:NO];
/* 設定每幾幀呼叫一次selector,預設為1 */
//[displayLink setPreferredFramesPerSecond:2];
/* 移除,不再使用 */
//[displayLink invalidate];
//displayLink = nil;
}
- (void) displayLink_SEL{
NSLog(@"displayLink is working!");
}
列印結果如下,每一幀都呼叫selector:
2018-02-01 11:48:02.707283+0800 IOSDemo[42328:4522489] displayLink is working!
2018-02-01 11:48:02.724375+0800 IOSDemo[42328:4522489] displayLink is working!
2018-02-01 11:48:02.742995+0800 IOSDemo[42328:4522489] displayLink is working!