日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

iOS关于RunLoop和Timer

發(fā)布時間:2025/3/14 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 iOS关于RunLoop和Timer 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

轉(zhuǎn)自:http://www.cnblogs.com/vicstudio/p/3281682.html

  RunLoop這個東西,其實我們一直在用,但一直沒有很好地理解它,或者甚至沒有知道它的存在。RunLoop可以說是每個線程都有的一個對象,是用來接受事件和分配任務(wù)的loop。永遠(yuǎn)不要手動創(chuàng)建一個runloop,它是跟隨著每個線程的。一個RunLoop接收兩種source的事件:input source和timer source。同時必須知道的是,input source,runloop是異步交付的,而timer source是同步交付的。每個runloop都有一個RunLoop Modes,代表它以何種方式執(zhí)行。

  我們?yōu)槭裁磸膩頉]有感覺到runloop的存在呢,是因為當(dāng)程序啟動,系統(tǒng)默認(rèn)幫我們啟動了一個主線程的runloop,并且一直在運行,直到程序退出。而用戶創(chuàng)建的子線程,runloop是需要手動啟動的,所以在線程里啟動timer或者調(diào)用performSelector: withObject:afterDelay:inModes: 是需要啟動runloop的。在后面我會介紹到怎么啟動。


關(guān)于input source :一般來說,input source基本我們用的就是下面幾種方式調(diào)用的:

Methods

Description

performSelectorOnMainThread: withObject: waitUntilDone: performSelectorOnMainThread: withObject: waitUntilDone:modes:

Performs the specified selector on the application’s main thread during that thread’s next run loop cycle. These methods give you the option of blocking the current thread until the selector is performed.

performSelector: onThread:withObject: waitUntilDone: performSelector: onThread:withObject: waitUntilDone:modes:

Performs the specified selector on any thread for which you have anNSThread?object. These methods give you the option of blocking the current thread until the selector is performed.

??
performSelector: withObject: afterDelay: performSelector: withObject: afterDelay:inModes:

Performs the specified selector on the current thread during the next run loop cycle and after an optional delay period. Because it waits until the next run loop cycle to perform the selector, these methods provide an automatic mini delay from the currently executing code. Multiple queued selectors are performed one after another in the order they were queued.

cancelPreviousPerformRequestsWithTarget: cancelPreviousPerformRequestsWithTarget: selector:object:

Lets you cancel a message sent to the current thread using the?performSelector: withObject: afterDelay:?orperformSelector: withObject: afterDelay:inModes:method.



這是系統(tǒng)幫我們封裝了一層,非常容易調(diào)用。用戶可以創(chuàng)建自己的Port-based input sources,用來監(jiān)聽某個端口的事件跟其他線程通信: - (void)addPort:(NSPort *)aPort forMode:(NSString *)mode;- (void)removePort:(NSPort *)aPort forMode:(NSString *)mode;

?

就是利用NSPort對象進行的消息傳遞和delegate,我們一般用不了,有興趣可以看看NSPort的介紹。

?

關(guān)于timer source:就是我們平時用到的NSTimer了。

?

至于我們什么時候需要用到runloop呢,主要是下面幾種情況:

1.需要用到NSPort或者其他input source跟其他線程通信。

2.在線程啟動timer。

3.在線程里調(diào)用performSelector...這類函數(shù)去調(diào)用。

?

下面我簡單用一個例子怎么在線程里啟動timer或者performSelector...如下:

-(void)testMain{//開啟一個測試子線程[NSThread detachNewThreadSelector:@selector(threadMethod) toTarget:self withObject:nil];}-(void)threadMethod{//沒用的timer//NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:.2 target:self selector:@selector(timerDone) userInfo:nil repeats:YES];//真正啟動了timerNSTimer *timer = [NSTimerscheduledTimerWithTimeInterval:.2target:selfselector:@selector(timerDone) userInfo:nilrepeats:YES];[[NSRunLoopcurrentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];[[NSRunLoopcurrentRunLoop] run];//同理,調(diào)用performSelector也一樣//[self performSelector:@selector(timerDone) withObject:nil afterDelay:.2];//[[NSRunLoop currentRunLoop] run];}-(void)timerDone{NSLog(@"Timer Run");}

?

NStimer,幾乎每個做iOS開發(fā)的程序員都用過,但是有一個關(guān)于Timer的介紹估計很多人都不知道:timer是不一定準(zhǔn)時的,是有可能被delay的,每次間隔的時間是不一定一樣的。

A repeating timer reschedules itself automatically based on the scheduled firing time, not the actual firing time. For example, if a timer is scheduled to fire at a particular time and every 5 seconds after that, the scheduled firing time will always fall on the original 5 second time intervals, even if the actual firing time gets delayed. If the firing time is delayed so much that it misses one or more of the scheduled firing times, the timer is fired only once for the missed time period. After firing for the missed period, the timer is rescheduled for the next scheduled firing time.?

簡單解讀一下:就是說一個repeat的timer,它在創(chuàng)建的時候就把每次的執(zhí)行時間算好了,而不是真正啟動的時候才計算下次的執(zhí)行時間。舉個例子,假如一個timer在一個特定的時間t激活,然后以間隔5秒的時間重復(fù)執(zhí)行。那么它的執(zhí)行操作的時間就應(yīng)該為t, t+5, t+10,... 假如它被延遲了,例如實際上timer在t+2的時候才啟動,那么它下次執(zhí)行的時間還是t+5,而并不是t+2+5,如果很不幸地在t+5還沒有啟動,那么它理應(yīng)該在t執(zhí)行的操作就跟下一次t+5的操作合為一個了。至于為什么會延遲呢,這就跟當(dāng)前線程的操作有關(guān),因為timer是同步交付的,所以假如當(dāng)前線程在執(zhí)行很復(fù)雜的運算時,那必須等待運算的完成才能調(diào)用timer,這就導(dǎo)致了timer的延遲。

我們就用一個例子來看看效果吧,代碼為:

//這里創(chuàng)建timer以每隔1秒執(zhí)行[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerDone) userInfo:nil repeats:YES];//這里在第3秒的時候模擬一個復(fù)雜運算[self performSelector:@selector(busyDone) withObject:nil afterDelay:3];-(void)busyDone {//這里模擬線程復(fù)雜的運算for(NSInteger i = 0; i< 0xffffffff;i++){}NSLog(@"BusgDone"); }-(void)timerDone {NSLog(@"Timer Run"); }

?

執(zhí)行結(jié)果為:

?

可以看到,timer本來都是以每隔1秒執(zhí)行,毫秒都是.564,然后在進行復(fù)雜的運算時候,timer直接被delay了,當(dāng)執(zhí)行完BusyDone之后,立即執(zhí)行了TimerRun,然后又在.564執(zhí)行了TimerRun,而不是距離上次執(zhí)行時間的1秒。

?

僅供參考。

轉(zhuǎn)載于:https://www.cnblogs.com/wangpei/p/3686022.html

總結(jié)

以上是生活随笔為你收集整理的iOS关于RunLoop和Timer的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。