關於定時器
1.NSTimer的建立
- 常用方法一:該方法內部自動新增到runloop中, 執行模式為預設
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];
// 如果在子執行緒中呼叫改方法,不會執行,因為子執行緒runloop必須手動開啟:
dispatch_async(dispatch_get_global_queue(0, 0), ^{
_timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(repeat:) userInfo:@{@"key":@"value"} repeats:true];
// 子執行緒runloop手動開啟
[[NSRunLoop currentRunLoop] run];
});
- 不常用方法二:該方法建立的NSTimer必須手動新增到runloop中
NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];
[runloop addTimer:timer forMode:NSDefaultRunLoopMode];
- 不常用方法三:兩個方法建立的NSTimer必須手動新增到runloop中
- (instancetype)initWithFireDate: interval: target: selector: userInfo: repeats:
- (void)initWithFireDate: interval: repeats: block:
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
2.NSTimer與Runloop:
- 為什麼NSTimer要新增到Runloop:
- NSTimer是一種source,所以的source要起作用,都要新增到runloop中
- 如果新增到了kCFRunLoopDefaultMode模式中,在拖動介面的時候,runloop模式只能唯一,這時切換為UITrackingRunLoopMode,定時器停止工作
- 如果新增到了kCFRunLoopCommonModes模式中,任何runloop模式都可以工作了
- Runloop的三種模式:
// 預設模式
kCFRunLoopDefaultMode
// 拖動模式
UITrackingRunLoopMode
// 此模式包含了以上兩種模式
kCFRunLoopCommonModes
3.NSTimer的迴圈引用
- 建立NSTimer時,最後一個引數如果為YES,那麼NSTimer對於target:self形成強引用;而self因為後續要用到定時器,所以對於定時器也形成了強引用;這就形成了迴圈引用
- 如果我們啟動了一個NSTimer,在某個介面釋放前,將這個NSTimer停止,甚至置為nil,都不能使這個介面釋放,原因是系統的迴圈池中還保有這個物件
4.如何解決迴圈引用
4.1.控制器不再引用NSTimer
4.2.NSTimer不再引用控制器
- fire方法
- 啟動 Timer, 觸發Target的方法呼叫但是並不會改變Timer的時間設定。 如果定時器的方法是non-repeating,呼叫之後自動銷燬
- (void)fire;
- 銷燬NSTimer的唯一辦法:(nstimer的建立和銷燬要在一個runloop中)
// 要在dealloc方法呼叫之前銷燬NSTimer
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
if (timer.isValid) {
// 從runloop中銷燬,銷燬系統對於NSTimer的強引用
[_timer invalidate];
// 將屬性置空銷燬,銷燬self對於NSTimer的強引用
_timer = nil;
}
}
.5.GCD定時器
- GCD 絕對精準,不受runloop影響
#import "ViewController.h"
@interface ViewController ()
/** 定時器屬性 */
@property (nonatomic, strong) dispatch_source_t timer;
@end
@implementation ViewController
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//1.建立GCD中的定時器
/*
第一個引數: source的型別DISPATCH_SOURCE_TYPE_TIMER 表示是定時器
第二個引數: 描述資訊,執行緒ID
第三個引數: 更詳細的描述資訊
第四個引數: 佇列,決定GCD定時器中的任務在哪個執行緒中執行
*/
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
//2.設定定時器(起始時間|間隔時間|精準度)
/*
第一個引數:定時器物件
第二個引數:起始時間,DISPATCH_TIME_NOW 從現在開始計時
第三個引數:間隔時間 2.0 GCD中時間單位為納秒
第四個引數:精準度 絕對精準0
*/
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
//3.設定定時器執行的任務
dispatch_source_set_event_handler(timer, ^{
NSLog(@"GCD---%@",[NSThread currentThread]);
});
//4.啟動執行
dispatch_resume(timer);
self.timer = timer;
}
@end
6.CADisplayLink定時器
- 建立CADisplayLink定時器
self.displayLink = [CADisplayLink displayLinkWithTarget:self sel:ector:@selector(handleDisplaylink:)];
[self.displayLink addToRunLoop:[NSRunLoop curentRunLoop] forMode:NSDefaultRunLoopMode];
- 停止CADisplayLink定時器
[self.displayLink invailidate];
self.displayLink = nil;
把CADisplayLink新增到runloop中後,方法就會被週期性呼叫。invailidate後,CADisplayLink從runloop中移除,方法停止呼叫
-
使用場景:
- 以螢幕的重新整理頻率執行某操作(重新整理頻率通常為60次/秒)
- 介面重繪,比如視訊播放
-
CADisplayLink延遲問題
- 如果執行的操作比較費時,會出現跳過執行操作的情況
相關文章
- 關於linux下定時器,多定時器Linux定時器
- 關於定時器週期、頻率等相關計算定時器
- 路由器WiFi定時開關設定教程 路由器WiFi定時開關怎麼設定?路由器WiFi
- BIOS相關定時器iOS定時器
- 關於beego的定時任務Go
- 基於51微控制器的定時器定時器
- 定時器定時器
- 定時器以及定時器的幾個案例定時器
- 分享一篇關於Python實現環形佇列高效定時器Python佇列定時器
- 直播app原始碼,定時開關,實現計時器功能APP原始碼
- 關於定時任務的一些雜談
- iOS定時器iOS定時器
- JavaScript定時器JavaScript定時器
- js定時器JS定時器
- JavaScript 定時器JavaScript定時器
- 核心定時器定時器
- 關於 MySQL 時區設定的一個常用 sql 命令MySql
- 關於做常規的數字定時滾動效果
- 純生JS輪播,定時器新增和清除定時器JS定時器
- java 中定時器Java定時器
- python定時器Python定時器
- Systemd 定時器教程定時器
- JMeter—定時器(八)JMeter定時器
- Go 的定時器Go定時器
- Python 定時器Python定時器
- android定時器Android定時器
- 閉包、定時器定時器
- jmeter(七)定時器JMeter定時器
- 整理:java定時器。Java定時器
- Android 定時器Android定時器
- JavaScript定時器演示JavaScript定時器
- TIM-定時器定時器
- STM32 定時器詳細篇(基於HAL庫)定時器
- 關於springboot如何做一個定時任務Spring Boot
- 關於oracle時區Oracle
- 如何設定電腦定時關機
- 關於locale的設定
- win10如何定時關機 win10定時關機的方法Win10