亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

iOS中最全的各種定時器使用教程

2020-07-26 02:41:40
字體:
來源:轉載
供稿:網友

前言

相信一說到定時器, 我們使用最多的就是NSTimer 和 GCD 了, 還有另外一個高級的定時器 CADisplayLink;,下面將給大家詳細介紹關于iOS定時器使用的相關內容,話不多說了,來一起看看詳細的介紹吧。

一. NSTimer

NSTimer的初始化方法有以下幾種:

會自動啟動, 并加入 MainRunloop 的 NSDefaultRunLoopMode 中,

注意: 這里的自動啟動, 并不是馬上就會啟動, 而是會延遲大概一個interval的時間:

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block

參數:

  • internal : 時間間隔, 多久調用一次
  • repeats: 是否重復調用
  • block: 需要重復做的事情

使用:

 [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {  static NSInteger num = 0;  NSLog(@"%ld", (long)num); num++;  if (num > 4) {  [timer invalidate];  NSLog(@"end"); } }];  NSLog(@"start");

這時, 控制臺的輸出:

2016-12-29 16:29:53.901 定時器[11673:278678] start2016-12-29 16:29:54.919 定時器[11673:278678] 02016-12-29 16:29:55.965 定時器[11673:278678] 12016-12-29 16:29:56.901 定時器[11673:278678] 22016-12-29 16:29:57.974 定時器[11673:278678] 32016-12-29 16:29:58.958 定時器[11673:278678] 42016-12-29 16:29:58.959 定時器[11673:278678] end

可以看出, 這里的internal設置為1s, 大概延遲了1s才開始執行block里的內容;

這里的停止定時器, 我直接在block里進行的, 如果使用一個全局變量來再其他地方手動停止定時器,需要這樣進行:

[self.timer invalidate];self.timer = nil;
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo

參數:

  • ti: 重復執行時間間隔
  • invocation: NSInvocation實例, 其用法見NSInvocation的基本用法
  • yesOrNo: 是否重復執行

示例:

// NSInvocation形式- (void)timer2 {  NSMethodSignature *method = [ViewController instanceMethodSignatureForSelector:@selector(invocationTimeRun:)];  NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:method]; NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 invocation:invocation repeats:YES];  // 設置方法調用者 invocation.target = self;  // 這里的SEL需要和NSMethodSignature中的一致 invocation.selector = @selector(invocationTimeRun:);  // 設置參數 // //這里的Index要從2開始,以為0跟1已經被占據了,分別是self(target),selector(_cmd) // 如果有多個參數, 可依次設置3 4 5 ... [invocation setArgument:&timer atIndex:2];  [invocation invoke];  NSLog(@"start");}- (void)invocationTimeRun:(NSTimer *)timer {  static NSInteger num = 0; NSLog(@"%ld---%@", (long)num, timer);  num++;  if (num > 4) { [timer invalidate]; }}

輸出:

2016-12-29 16:52:54.029 定時器[12089:289673] 0---<__NSCFTimer: 0x60000017d940>2016-12-29 16:52:54.029 定時器[12089:289673] start2016-12-29 16:52:55.104 定時器[12089:289673] 1---<__NSCFTimer: 0x60000017d940>2016-12-29 16:52:56.095 定時器[12089:289673] 2---<__NSCFTimer: 0x60000017d940>2016-12-29 16:52:57.098 定時器[12089:289673] 3---<__NSCFTimer: 0x60000017d940>2016-12-29 16:52:58.094 定時器[12089:289673] 4---<__NSCFTimer: 0x60000017d940>

可以看出, 這里定時器是立馬就執行了, 沒有延遲;

此方法可以傳遞多個參數, 下面是傳遞兩個參數的示例:

// NSInvocation形式- (void)timer2 {  NSMethodSignature *method = [ViewController instanceMethodSignatureForSelector:@selector(invocationTimeRun:des:)];  NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:method]; NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 invocation:invocation repeats:YES];  // 設置方法調用者 invocation.target = self;  // 這里的SEL需要和NSMethodSignature中的一致 invocation.selector = @selector(invocationTimeRun:des:);  // 設置參數 // //這里的Index要從2開始,以為0跟1已經被占據了,分別是self(target),selector(_cmd) // 如果有多個參數, 可依次設置3 4 5 ... [invocation setArgument:&timer atIndex:2]; // 設置第二個參數 NSString *dsc = @"第二個參數是字符串"; [invocation setArgument:&dsc atIndex:3];  [invocation invoke];  NSLog(@"start");}- (void)invocationTimeRun:(NSTimer *)timer des:(NSString *)dsc {  static NSInteger num = 0; NSLog(@"%ld---%@--%@", (long)num, timer, dsc);  num++;  if (num > 4) { [timer invalidate]; }}

輸出:

2016-12-29 16:57:45.087 定時器[12183:292324] 0---<__NSCFTimer: 0x60000016dbc0>--第二個參數是字符串2016-12-29 16:57:45.088 定時器[12183:292324] start2016-12-29 16:57:46.161 定時器[12183:292324] 1---<__NSCFTimer: 0x60000016dbc0>--第二個參數是字符串2016-12-29 16:57:47.161 定時器[12183:292324] 2---<__NSCFTimer: 0x60000016dbc0>--第二個參數是字符串2016-12-29 16:57:48.150 定時器[12183:292324] 3---<__NSCFTimer: 0x60000016dbc0>--第二個參數是字符串2016-12-29 16:57:49.159 定時器[12183:292324] 4---<__NSCFTimer: 0x60000016dbc0>--第二個參數是字符串
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo

參數:

  • ti: 時間間隔
  • aTarget: 調用者
  • aSelector: 執行的方法
  • userInfo: 參數
  • yesOrNo: 是否重復執行

示例:

- (void)timer3 {  NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(targetRun:) userInfo:@"這是攜帶的參數" repeats:YES];  NSLog(@"start");}- (void)targetRun:(NSTimer *)timer {  static NSInteger num = 0;  NSLog(@"%ld---%@--%@", (long)num, timer, timer.userInfo);  num++;  if (num > 4) { [timer invalidate]; }}

輸出:

2016-12-29 17:05:11.590 定時器[12328:296879] start2016-12-29 17:05:12.655 定時器[12328:296879] 0---<__NSCFTimer: 0x608000162700>--這是攜帶的參數2016-12-29 17:05:13.661 定時器[12328:296879] 1---<__NSCFTimer: 0x608000162700>--這是攜帶的參數2016-12-29 17:05:14.664 定時器[12328:296879] 2---<__NSCFTimer: 0x608000162700>--這是攜帶的參數2016-12-29 17:05:15.651 定時器[12328:296879] 3---<__NSCFTimer: 0x608000162700>--這是攜帶的參數2016-12-29 17:05:16.650 定時器[12328:296879] 4---<__NSCFTimer: 0x608000162700>--這是攜帶的參數

下面這三種方式創建定時器的用法, 和上面相應的方法類似, 需要注意的是, 這樣創建的定時器, 并不會執行, 需要我們手動來開啟定時器;

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo

開啟的方式是, 將當前定時器添加到RunLoop中:

[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

下面給出一個示例:

- (void)timer4 {  NSTimer *timer = [NSTimer timerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {  static NSInteger num = 0;  NSLog(@"%ld", (long)num); num++;  if (num > 4) {  [timer invalidate]; timer = nil;  NSLog(@"end"); } }];  [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];  NSLog(@"start");}

輸出:

2016-12-29 17:12:13.955 定時器[12498:301751] start2016-12-29 17:12:15.013 定時器[12498:301751] 02016-12-29 17:12:16.018 定時器[12498:301751] 12016-12-29 17:12:17.011 定時器[12498:301751] 22016-12-29 17:12:18.024 定時器[12498:301751] 32016-12-29 17:12:19.023 定時器[12498:301751] 42016-12-29 17:12:19.023 定時器[12498:301751] end

定時器基本的創建方式就這些了, 還可以設置其他的屬性, 例如開啟時間, 這些直接參考其API 進行設置即可;

注意: 以上實例中, 我沒有使用全局的NSTimer 對象, 如果設置全局變量, 或者設置為屬性, 在停止定時器的時候要手動置為nil, 即:

[timer invalidate]; timer = nil;

二. GCD

dispatch_after : 延遲執行一次

dispatch_after(dispatch_time_t when, dispatch_queue_t queue, dispatch_block_t block)

示例:

- (void)gcdTimer {  // 延遲2s dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC);  dispatch_after(delayTime, dispatch_get_main_queue(), ^(void){  NSLog(@"延遲2s后執行"); });  NSLog(@"start");}

重復執行的定時器

voiddispatch_source_set_timer(dispatch_source_t source, dispatch_time_t start, uint64_t interval, uint64_t leeway)

參數:

  • source: 定時器
  • start: 開始時間, 當我們使用 dispatch_time 或者 DISPATCH_TIME_NOW 時,系統會使用默認時鐘來進行計時。然而當系統休眠的時候,默認時鐘是不走的,也就會導致計時器停止。使用 dispatch_walltime 可以讓計時器按照真實時間間隔進行計時;
  • interval: 間隔(如果設置為 DISPATCH_TIME_FOREVER 則只執行一次)
  • leeway: 允許的誤差范圍; 計時不可能是百分百精確的, 即使設置為0, 也不是百分百精確的, 所以可以設置合理的允許誤差, 單位: 納秒(NSEC_PER_SEC)

相關內容, 可參考文章: Dispatch Source Timer 的使用以及注意事項

// 重復執行的定時器- (void)gcdTimer1 {  // 獲取全局隊列 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 start = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)); // dispatch_time_t start = dispatch_walltime(NULL, 0);  // 重復間隔 uint64_t interval = (uint64_t)(1.0 * NSEC_PER_SEC);  // 設置定時器 dispatch_source_set_timer(_timer, start, interval, 0);  // 設置需要執行的事件 dispatch_source_set_event_handler(_timer, ^{  //在這里執行事件 static NSInteger num = 0;  NSLog(@"%ld", (long)num); num++;  if (num > 4) {  NSLog(@"end");  // 關閉定時器 dispatch_source_cancel(_timer); } }); // 開啟定時器 dispatch_resume(_timer);  NSLog(@"start");}

輸出:

2016-12-30 10:15:01.114 定時器[3393:99474] start2016-12-30 10:15:02.187 定時器[3393:99796] 02016-12-30 10:15:03.114 定時器[3393:99796] 12016-12-30 10:15:04.186 定時器[3393:99796] 22016-12-30 10:15:05.188 定時器[3393:99796] 32016-12-30 10:15:06.188 定時器[3393:99796] 42016-12-30 10:15:06.188 定時器[3393:99796] end

這里的開始時間設置了1s的間隔, 所以1s之后才開始執行,可以設置使用DISPATCH_TIME_NOW來立馬執行;

注意:

這里的開始時間(start)可以使用下面的方式的來設置:

dispatch_time_t start = dispatch_walltime(NULL, 0);

或者直接設置為: DISPATCH_TIME_NOW

關于 dispatch_walltime 和 dispatch_time 的區別, 上面也有提及,也可參考stackOverflow上的這個回答; 主要區別就是前者在系統休眠時還會繼續計時, 而后者在系統休眠時就停止計時, 待系統重新激活時, 接著繼續計時;

停止計時器:

停止GCD定時器的方式, Dispatch Source Timer 的使用以及注意事項中有提及, 主要有以下兩種:

// 關閉定時器// 完全銷毀定時器, 重新開啟的話需要重新創建// 全局變量, 關閉后需要置為nildispatch_source_cancel(_timer); // 暫停定時器// 可使用dispatch_resume(_timer)再次開啟// 全局變量, 暫停后不能置為nil, 否則不能重新開啟dispatch_suspend(_timer);

三. CADisplayLink

CADisplayLink默認每秒運行60次,通過它的 frameInterval 屬性改變每秒運行幀數,如設置為2,意味CADisplayLink每隔一幀運行一次,有效的邏輯每秒運行30次

屏幕刷新時調用:CADisplayLink是一個能讓我們以和屏幕刷新率同步的頻率將特定的內容畫到屏幕上的定時器類。CADisplayLink以特定模式注冊到runloop后,每當屏幕顯示內容刷新結束的時候,runloop就會向CADisplayLink指定的target發送一次指定的selector消息, CADisplayLink類對應的selector就會被調用一次。所以通常情況下,按照iOS設備屏幕的刷新率60次/秒

延遲:iOS設備的屏幕刷新頻率是固定的,CADisplayLink在正常情況下會在每次刷新結束都被調用,精確度相當高。但如果調用的方法比較耗時,超過了屏幕刷新周期,就會導致跳過若干次回調調用機會。

如果CPU過于繁忙,無法保證屏幕60次/秒的刷新率,就會導致跳過若干次調用回調方法的機會,跳過次數取決CPU的忙碌程度。

使用場景:從原理上可以看出,CADisplayLink適合做界面的不停重繪,比如視頻播放的時候需要不停地獲取下一幀用于界面渲染。

+ (CADisplayLink *)displayLinkWithTarget:(id)target selector:(SEL)sel

參數:

  • target: 調用者
  • sel: 執行的方法

示例:

- (void) displayLink {  CADisplayLink *display = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayRun:)];  // 大概1s執行一次// 取值范圍 1--100, 值越大, 頻率越高 display.preferredFramesPerSecond = 2;  [display addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];}- (void)displayRun:(CADisplayLink *)link {  static NSInteger num = 0;  NSLog(@"%ld", (long)num); num++;  if (num > 4) {  [link invalidate];  NSLog(@"end"); }}

這里的示例不太恰當, 不應該在這種場合使用,

另外, 我們可以使用他的 paused 屬性, 來使其暫停, 或繼續:

// 暫停 display.paused = YES;// 繼續 display.paused = NO;

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對武林網的支持。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美日韩视频在线| 欧美激情亚洲国产| 日本精品性网站在线观看| 国产精品久久77777| 欧美肥婆姓交大片| 亚洲色图50p| 国产精品电影网站| 丝袜亚洲另类欧美重口| 日韩精品一区二区视频| 国产日韩欧美自拍| www国产亚洲精品久久网站| 欧美国产日产韩国视频| 韩日欧美一区二区| 日韩a**站在线观看| 亚洲淫片在线视频| 亚洲国产成人爱av在线播放| 日韩av黄色在线观看| 日韩精品一二三四区| 91成人精品网站| 在线观看日韩视频| 久久久免费高清电视剧观看| 久久精品国产欧美亚洲人人爽| 国产亚洲欧洲高清| 91欧美激情另类亚洲| 日韩美女免费观看| 91国自产精品中文字幕亚洲| 色狠狠av一区二区三区香蕉蜜桃| 日韩久久精品成人| 中文字幕日韩在线视频| 亚洲国产成人在线播放| 91精品国产高清自在线看超| 成人字幕网zmw| 欧美疯狂性受xxxxx另类| 欧美成人午夜视频| 91探花福利精品国产自产在线| 欧美性生交大片免网| 国产精品网站入口| 欧美成人免费在线视频| 国产精品视频男人的天堂| 久久精品久久久久久国产 免费| 亚洲国产中文字幕久久网| 日韩极品精品视频免费观看| 国产欧美精品va在线观看| 最新国产成人av网站网址麻豆| 最新日韩中文字幕| 亚洲综合精品一区二区| 97国产suv精品一区二区62| 精品国产精品三级精品av网址| 久青草国产97香蕉在线视频| 亚洲香蕉成人av网站在线观看| 丁香五六月婷婷久久激情| 国产欧美一区二区三区四区| 国产精品美乳一区二区免费| 久久这里有精品| 国产欧洲精品视频| 91精品久久久久久久久久入口| 国产欧美在线观看| 秋霞成人午夜鲁丝一区二区三区| 欧美午夜丰满在线18影院| 国产免费一区二区三区在线观看| 在线亚洲午夜片av大片| 日韩欧美在线播放| 国产一区二区丝袜| 亚洲a区在线视频| 亚洲美女激情视频| 色综合久久88色综合天天看泰| 91精品国产综合久久香蕉922| 国产91在线高潮白浆在线观看| 亚洲久久久久久久久久| 欧美日韩国产在线看| 亚洲在线视频观看| 精品久久久久久中文字幕大豆网| 亚洲国产精品成人一区二区| 欧美高清在线观看| 久久久久久综合网天天| 一区二区三区www| 菠萝蜜影院一区二区免费| 伊人久久综合97精品| 国产一区二区丝袜高跟鞋图片| 日韩视频亚洲视频| 性欧美办公室18xxxxhd| 久久av红桃一区二区小说| 亚洲国产精品专区久久| 日韩高清电影免费观看完整版| 中文字幕视频在线免费欧美日韩综合在线看| 欧美猛交免费看| 欧美激情videos| 日韩av快播网址| 日韩av观看网址| 96sao精品视频在线观看| 亚洲一区二区少妇| 国产成人综合久久| 在线观看亚洲视频| 26uuu日韩精品一区二区| 成人亚洲综合色就1024| 国产精品久久久91| 久热精品视频在线观看| 亚洲欧美日韩中文在线制服| 久久综合五月天| 亚洲四色影视在线观看| 一区二区欧美久久| 性欧美在线看片a免费观看| 久久久久久久久久国产精品| 在线日韩日本国产亚洲| 久久视频免费在线播放| 92看片淫黄大片欧美看国产片| 亚洲欧美www| 亚洲三级av在线| 日本aⅴ大伊香蕉精品视频| 日韩欧美精品网站| 国产suv精品一区二区三区88区| 成人精品网站在线观看| 久久久精品久久久久| www.99久久热国产日韩欧美.com| 色偷偷偷综合中文字幕;dd| 91国产一区在线| 91国产中文字幕| 国产色视频一区| 亚洲的天堂在线中文字幕| 亚洲精品综合精品自拍| 日韩高清欧美高清| 亚洲综合在线中文字幕| 欧美电影电视剧在线观看| 亚洲精品v欧美精品v日韩精品| 国产精品高潮呻吟久久av黑人| 欧美激情一区二区三区成人| 国产综合在线视频| 欧美最猛性xxxxx免费| 最新亚洲国产精品| 国产精品嫩草视频| 欧美激情图片区| 午夜精品三级视频福利| 成人黄色免费片| 欧美激情一级精品国产| 欧美成人免费小视频| 成人xvideos免费视频| 中文字幕在线视频日韩| 欧美野外wwwxxx| 国产精品久久综合av爱欲tv| 国产欧美一区二区三区视频| 日韩欧美在线视频日韩欧美在线视频| 在线观看国产欧美| 国产成人精品999| 欧美日韩在线观看视频小说| 久久精品亚洲94久久精品| 国产精品国产福利国产秒拍| 成人福利网站在线观看| 精品国产乱码久久久久酒店| 国产精品福利片| 欧美激情xxxx| 亚洲一区久久久| 亚洲欧洲视频在线| 美女久久久久久久| 久久偷看各类女兵18女厕嘘嘘| 亚洲午夜色婷婷在线| 成人免费观看网址| 91地址最新发布| 日韩中文字在线| 91在线色戒在线| 日本中文字幕不卡免费| 精品调教chinesegay| 日韩高清电影免费观看完整版| 久久精品91久久久久久再现| 久久综合伊人77777尤物|