亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

iOS中最全的各種定時(shí)器使用教程

 更新時(shí)間:2017年09月13日 08:33:03   作者:流火緋瞳  
這篇文章主要給大家介紹了關(guān)于iOS中最全的各種定時(shí)器的使用教程,文中通過(guò)示例代碼介紹的非常詳細(xì),通過(guò)文中介紹的最全的定時(shí)器相信會(huì)對(duì)各位iOS開(kāi)發(fā)者們帶來(lái)一定的幫助,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。

前言

相信一說(shuō)到定時(shí)器, 我們使用最多的就是NSTimer 和 GCD 了, 還有另外一個(gè)高級(jí)的定時(shí)器 CADisplayLink;,下面將給大家詳細(xì)介紹關(guān)于iOS定時(shí)器使用的相關(guān)內(nèi)容,話(huà)不多說(shuō)了,來(lái)一起看看詳細(xì)的介紹吧。

一. NSTimer

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

會(huì)自動(dòng)啟動(dòng), 并加入 MainRunloop 的 NSDefaultRunLoopMode 中,

注意: 這里的自動(dòng)啟動(dòng), 并不是馬上就會(huì)啟動(dòng), 而是會(huì)延遲大概一個(gè)interval的時(shí)間:

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

參數(shù):

  • internal : 時(shí)間間隔, 多久調(diào)用一次
  • repeats: 是否重復(fù)調(diào)用
  • block: 需要重復(fù)做的事情

使用:

 [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");

這時(shí), 控制臺(tái)的輸出:

2016-12-29 16:29:53.901 定時(shí)器[11673:278678] start
2016-12-29 16:29:54.919 定時(shí)器[11673:278678] 0
2016-12-29 16:29:55.965 定時(shí)器[11673:278678] 1
2016-12-29 16:29:56.901 定時(shí)器[11673:278678] 2
2016-12-29 16:29:57.974 定時(shí)器[11673:278678] 3
2016-12-29 16:29:58.958 定時(shí)器[11673:278678] 4
2016-12-29 16:29:58.959 定時(shí)器[11673:278678] end

可以看出, 這里的internal設(shè)置為1s, 大概延遲了1s才開(kāi)始執(zhí)行block里的內(nèi)容;

這里的停止定時(shí)器, 我直接在block里進(jìn)行的, 如果使用一個(gè)全局變量來(lái)再其他地方手動(dòng)停止定時(shí)器,需要這樣進(jìn)行:

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

參數(shù):

  • ti: 重復(fù)執(zhí)行時(shí)間間隔
  • invocation: NSInvocation實(shí)例, 其用法見(jiàn)NSInvocation的基本用法
  • yesOrNo: 是否重復(fù)執(zhí)行

示例:

// NSInvocation形式
- (void)timer2 {
 
 NSMethodSignature *method = [ViewController instanceMethodSignatureForSelector:@selector(invocationTimeRun:)];
 
 NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:method];
 NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 invocation:invocation repeats:YES];
 
 // 設(shè)置方法調(diào)用者
 invocation.target = self;
 
 // 這里的SEL需要和NSMethodSignature中的一致
 invocation.selector = @selector(invocationTimeRun:);
 
 // 設(shè)置參數(shù)
 // //這里的Index要從2開(kāi)始,以為0跟1已經(jīng)被占據(jù)了,分別是self(target),selector(_cmd)
 // 如果有多個(gè)參數(shù), 可依次設(shè)置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 定時(shí)器[12089:289673] 0---<__NSCFTimer: 0x60000017d940>
2016-12-29 16:52:54.029 定時(shí)器[12089:289673] start
2016-12-29 16:52:55.104 定時(shí)器[12089:289673] 1---<__NSCFTimer: 0x60000017d940>
2016-12-29 16:52:56.095 定時(shí)器[12089:289673] 2---<__NSCFTimer: 0x60000017d940>
2016-12-29 16:52:57.098 定時(shí)器[12089:289673] 3---<__NSCFTimer: 0x60000017d940>
2016-12-29 16:52:58.094 定時(shí)器[12089:289673] 4---<__NSCFTimer: 0x60000017d940>

可以看出, 這里定時(shí)器是立馬就執(zhí)行了, 沒(méi)有延遲;

此方法可以傳遞多個(gè)參數(shù), 下面是傳遞兩個(gè)參數(shù)的示例:

// 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];
 
 // 設(shè)置方法調(diào)用者
 invocation.target = self;
 
 // 這里的SEL需要和NSMethodSignature中的一致
 invocation.selector = @selector(invocationTimeRun:des:);
 
 // 設(shè)置參數(shù)
 // //這里的Index要從2開(kāi)始,以為0跟1已經(jīng)被占據(jù)了,分別是self(target),selector(_cmd)
 // 如果有多個(gè)參數(shù), 可依次設(shè)置3 4 5 ...
 [invocation setArgument:&timer atIndex:2];
 // 設(shè)置第二個(gè)參數(shù)
 NSString *dsc = @"第二個(gè)參數(shù)是字符串";
 [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 定時(shí)器[12183:292324] 0---<__NSCFTimer: 0x60000016dbc0>--第二個(gè)參數(shù)是字符串
2016-12-29 16:57:45.088 定時(shí)器[12183:292324] start
2016-12-29 16:57:46.161 定時(shí)器[12183:292324] 1---<__NSCFTimer: 0x60000016dbc0>--第二個(gè)參數(shù)是字符串
2016-12-29 16:57:47.161 定時(shí)器[12183:292324] 2---<__NSCFTimer: 0x60000016dbc0>--第二個(gè)參數(shù)是字符串
2016-12-29 16:57:48.150 定時(shí)器[12183:292324] 3---<__NSCFTimer: 0x60000016dbc0>--第二個(gè)參數(shù)是字符串
2016-12-29 16:57:49.159 定時(shí)器[12183:292324] 4---<__NSCFTimer: 0x60000016dbc0>--第二個(gè)參數(shù)是字符串
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo

參數(shù):

  • ti: 時(shí)間間隔
  • aTarget: 調(diào)用者
  • aSelector: 執(zhí)行的方法
  • userInfo: 參數(shù)
  • yesOrNo: 是否重復(fù)執(zhí)行

示例:

- (void)timer3 {
 
 NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(targetRun:) userInfo:@"這是攜帶的參數(shù)" 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 定時(shí)器[12328:296879] start
2016-12-29 17:05:12.655 定時(shí)器[12328:296879] 0---<__NSCFTimer: 0x608000162700>--這是攜帶的參數(shù)
2016-12-29 17:05:13.661 定時(shí)器[12328:296879] 1---<__NSCFTimer: 0x608000162700>--這是攜帶的參數(shù)
2016-12-29 17:05:14.664 定時(shí)器[12328:296879] 2---<__NSCFTimer: 0x608000162700>--這是攜帶的參數(shù)
2016-12-29 17:05:15.651 定時(shí)器[12328:296879] 3---<__NSCFTimer: 0x608000162700>--這是攜帶的參數(shù)
2016-12-29 17:05:16.650 定時(shí)器[12328:296879] 4---<__NSCFTimer: 0x608000162700>--這是攜帶的參數(shù)

下面這三種方式創(chuàng)建定時(shí)器的用法, 和上面相應(yīng)的方法類(lèi)似, 需要注意的是, 這樣創(chuàng)建的定時(shí)器, 并不會(huì)執(zhí)行, 需要我們手動(dòng)來(lái)開(kāi)啟定時(shí)器;

+ (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

開(kāi)啟的方式是, 將當(dāng)前定時(shí)器添加到RunLoop中:

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

下面給出一個(gè)示例:

- (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 定時(shí)器[12498:301751] start
2016-12-29 17:12:15.013 定時(shí)器[12498:301751] 0
2016-12-29 17:12:16.018 定時(shí)器[12498:301751] 1
2016-12-29 17:12:17.011 定時(shí)器[12498:301751] 2
2016-12-29 17:12:18.024 定時(shí)器[12498:301751] 3
2016-12-29 17:12:19.023 定時(shí)器[12498:301751] 4
2016-12-29 17:12:19.023 定時(shí)器[12498:301751] end

定時(shí)器基本的創(chuàng)建方式就這些了, 還可以設(shè)置其他的屬性, 例如開(kāi)啟時(shí)間, 這些直接參考其API 進(jìn)行設(shè)置即可;

注意: 以上實(shí)例中, 我沒(méi)有使用全局的NSTimer 對(duì)象, 如果設(shè)置全局變量, 或者設(shè)置為屬性, 在停止定時(shí)器的時(shí)候要手動(dòng)置為nil, 即:

[timer invalidate];
 timer = nil;

二. GCD

dispatch_after : 延遲執(zhí)行一次

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后執(zhí)行");
 });
 
 NSLog(@"start");
}

重復(fù)執(zhí)行的定時(shí)器

void
dispatch_source_set_timer(dispatch_source_t source,
 dispatch_time_t start,
 uint64_t interval,
 uint64_t leeway)

參數(shù):

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

相關(guān)內(nèi)容, 可參考文章: Dispatch Source Timer 的使用以及注意事項(xiàng)

// 重復(fù)執(zhí)行的定時(shí)器
- (void)gcdTimer1 {
 
 // 獲取全局隊(duì)列
 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
 // 創(chuàng)建定時(shí)器
 dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
 
 // 開(kāi)始時(shí)間
 dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC));
 
// dispatch_time_t start = dispatch_walltime(NULL, 0);
 
 // 重復(fù)間隔
 uint64_t interval = (uint64_t)(1.0 * NSEC_PER_SEC);
 
 // 設(shè)置定時(shí)器
 dispatch_source_set_timer(_timer, start, interval, 0);
 
 // 設(shè)置需要執(zhí)行的事件
 dispatch_source_set_event_handler(_timer, ^{
 
 //在這里執(zhí)行事件
 static NSInteger num = 0;
 
 NSLog(@"%ld", (long)num);
 num++;
 
 if (num > 4) {
 
 NSLog(@"end");
 
 // 關(guān)閉定時(shí)器
 dispatch_source_cancel(_timer);
 }
 });
 // 開(kāi)啟定時(shí)器
 dispatch_resume(_timer);
 
 NSLog(@"start");
}

輸出:

2016-12-30 10:15:01.114 定時(shí)器[3393:99474] start
2016-12-30 10:15:02.187 定時(shí)器[3393:99796] 0
2016-12-30 10:15:03.114 定時(shí)器[3393:99796] 1
2016-12-30 10:15:04.186 定時(shí)器[3393:99796] 2
2016-12-30 10:15:05.188 定時(shí)器[3393:99796] 3
2016-12-30 10:15:06.188 定時(shí)器[3393:99796] 4
2016-12-30 10:15:06.188 定時(shí)器[3393:99796] end

這里的開(kāi)始時(shí)間設(shè)置了1s的間隔, 所以1s之后才開(kāi)始執(zhí)行,可以設(shè)置使用DISPATCH_TIME_NOW來(lái)立馬執(zhí)行;

注意:

這里的開(kāi)始時(shí)間(start)可以使用下面的方式的來(lái)設(shè)置:

dispatch_time_t start = dispatch_walltime(NULL, 0);

或者直接設(shè)置為: DISPATCH_TIME_NOW

關(guān)于 dispatch_walltime 和 dispatch_time 的區(qū)別, 上面也有提及,也可參考stackOverflow上的這個(gè)回答; 主要區(qū)別就是前者在系統(tǒng)休眠時(shí)還會(huì)繼續(xù)計(jì)時(shí), 而后者在系統(tǒng)休眠時(shí)就停止計(jì)時(shí), 待系統(tǒng)重新激活時(shí), 接著繼續(xù)計(jì)時(shí);

停止計(jì)時(shí)器:

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

// 關(guān)閉定時(shí)器
// 完全銷(xiāo)毀定時(shí)器, 重新開(kāi)啟的話(huà)需要重新創(chuàng)建
// 全局變量, 關(guān)閉后需要置為nil
dispatch_source_cancel(_timer);
 
// 暫停定時(shí)器
// 可使用dispatch_resume(_timer)再次開(kāi)啟
// 全局變量, 暫停后不能置為nil, 否則不能重新開(kāi)啟
dispatch_suspend(_timer);

三. CADisplayLink

CADisplayLink默認(rèn)每秒運(yùn)行60次,通過(guò)它的 frameInterval 屬性改變每秒運(yùn)行幀數(shù),如設(shè)置為2,意味CADisplayLink每隔一幀運(yùn)行一次,有效的邏輯每秒運(yùn)行30次

屏幕刷新時(shí)調(diào)用:CADisplayLink是一個(gè)能讓我們以和屏幕刷新率同步的頻率將特定的內(nèi)容畫(huà)到屏幕上的定時(shí)器類(lèi)。CADisplayLink以特定模式注冊(cè)到runloop后,每當(dāng)屏幕顯示內(nèi)容刷新結(jié)束的時(shí)候,runloop就會(huì)向CADisplayLink指定的target發(fā)送一次指定的selector消息, CADisplayLink類(lèi)對(duì)應(yīng)的selector就會(huì)被調(diào)用一次。所以通常情況下,按照iOS設(shè)備屏幕的刷新率60次/秒

延遲:iOS設(shè)備的屏幕刷新頻率是固定的,CADisplayLink在正常情況下會(huì)在每次刷新結(jié)束都被調(diào)用,精確度相當(dāng)高。但如果調(diào)用的方法比較耗時(shí),超過(guò)了屏幕刷新周期,就會(huì)導(dǎo)致跳過(guò)若干次回調(diào)調(diào)用機(jī)會(huì)。

如果CPU過(guò)于繁忙,無(wú)法保證屏幕60次/秒的刷新率,就會(huì)導(dǎo)致跳過(guò)若干次調(diào)用回調(diào)方法的機(jī)會(huì),跳過(guò)次數(shù)取決CPU的忙碌程度。

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

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

參數(shù):

  • target: 調(diào)用者
  • sel: 執(zhí)行的方法

示例:

- (void) displayLink {
 
 CADisplayLink *display = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayRun:)];
 
 // 大概1s執(zhí)行一次
// 取值范圍 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");
 }
}

這里的示例不太恰當(dāng), 不應(yīng)該在這種場(chǎng)合使用,

另外, 我們可以使用他的 paused 屬性, 來(lái)使其暫停, 或繼續(xù):

// 暫停
 display.paused = YES;
// 繼續(xù)
 display.paused = NO;

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

最新評(píng)論