介紹:
“消息”循環(huán)戴陡,等待消息(會休眠)->接收消息->處理消息。通過上面的代碼耗啦,runloop本質就是提供了一種消息處理模式,只不過它封裝抽象的太好了(一般開發(fā)的時候根本就感覺不到半夷,或者說不用關心)。
runloop相當于幫我們打包了各種消息迅细,并將消息發(fā)送給指定的接受者巫橄。“
可以將runloop理解為一個函數(shù)茵典,功能是一個消息循環(huán)湘换,有消息則處理,沒有消息則休眠统阿。
(注意:runloop實質是一個對象彩倚,但是不影響以上的假設)
線程剛創(chuàng)建時并沒有 RunLoop,如果你不主動獲取扶平,那它一直都不會有帆离。RunLoop 的創(chuàng)建是發(fā)生在第一次獲取時,RunLoop 的銷毀是發(fā)生在線程結束時结澄。你只能在一個線程的內部獲取其 RunLoop(主線程除外)哥谷。
系統(tǒng)為我們提供了多種模式,下面列一些比較常遇到的:
kCFRunLoopDefaultMode: App的默認 Mode,通常主線程是在這個 Mode 下運行的麻献。
UITrackingRunLoopMode: 界面跟蹤 Mode们妥,用于 ScrollView 追蹤觸摸滑動,保證界面滑動時不受其他 Mode 影響勉吻。
UIInitializationRunLoopMode: 在剛啟動 App 時第進入的第一個 Mode监婶,啟動完成后就不再使用。
NSRunLoopCommonModes: 包含了多種模式:default, modal, 和tracking modes齿桃。
參考:
runloop 和線程的關系:
1 run oop和線程是緊密相連的源譬,可以這樣說run loop是為了線程而生集惋,沒有線程,它就沒有存在的必要踩娘。Run loops是線程的基礎架構部分
2 一條線程對應一個RunLoop對象刮刑,每條線程都有唯一一個與之對應的RunLoop對象。
3 我們只能在當前線程中操作當前線程的RunLoop养渴,而不能去操作其他線程的RunLoop雷绢。
4 RunLoop對象在第一次獲取RunLoop時創(chuàng)建,銷毀則是在線程結束的時候理卑。
5 主線程的RunLoop對象系統(tǒng)自動幫助我們創(chuàng)建好了(原理如下)翘紊,而子線程的RunLoop對象需要我們主動創(chuàng)建。
使用:
1藐唠、NSTimer的創(chuàng)建使用
當實例化NSTimer對象的時候帆疟,通常會使用 scheduledTimerWithTimeInterval 方法鹉究。該方法會自動為我們實例化的timer添加到當前線程的RunLoop中,并且默認模式是?NSDefaultRunLoopMode踪宠。但當前線程是主線程時自赔,某些UI事件,比如ScrollView正在拖動柳琢,將會RunLoop切換成 NSEventTrackingRunLoopMode 模式绍妨,在這個模式下,默認的?NSDefaultRunLoopMode 模式中注冊的事件是不會執(zhí)行的柬脸。也就是說他去,使用?scheduledTimerWithTimeInterval 方法添加到RunLoop中的Timer就不會執(zhí)行。
為了設置一個不被UI干擾的Timer倒堕,我們需要手動創(chuàng)建一個Timer灾测,然后使用RunLoop的 addTimer:forMode: 方法來把Timer按照指定的模式加入到RunLoop中。這里使用?NSRunLoopCommonModes 模式涩馆,這個模式相當于?NSDefaultRunLoopMode 和?NSEventTrackingRunLoopMode 的結合行施。
2 ImageView推遲顯示
一些動畫執(zhí)行過程中,
或者scrllview滑動過程匯總image的顯示
[cell performSelector:@selector(setImage)withObject:nil afterDelay:0 inModes:@[NSDefaultRunLoopMode]];
[imageview?performSelector: inModes: ]
3 后臺常駐線程(很常用)
我們在開發(fā)應用程序的過程中魂那,如果后臺操作特別頻繁牍汹,經(jīng)常會在子線程做一些耗時操作(下載文件鲜侥、后臺播放音樂等),我們最好能讓這條線程永遠常駐內存瘸爽。
那么怎么做呢展运?
添加一條用于常駐內存的強引用的子線程活逆,在該線程的RunLoop下添加一個Sources,開啟RunLoop拗胜。
具體實現(xiàn)過程如下:
在項目的ViewController.m中添加一條強引用的thread線程屬性蔗候,如下圖:
在viewDidLoad中創(chuàng)建線程self.thread,使線程啟動并執(zhí)行run1方法埂软,代碼如下锈遥。在Demo中,請在viewDidLoad調用[self showDemo4];方法勘畔。
運行之后發(fā)現(xiàn)打印了----run1-----所灸,而未開啟RunLoop則未打印。
這時炫七,我們就開啟了一條常駐線程爬立,下邊我們來試著添加其他任務,除了之前創(chuàng)建的時候調用了run1方法万哪,我們另外在點擊的時候調用run2方法侠驯。
那么抡秆,我們在touchesBegan中調用PerformSelector,從而實現(xiàn)在點擊屏幕的時候調用run2方法吟策。具體代碼如下:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{ ? ? ? //利用performSelector儒士,在self.thread的線程中調用run2方法執(zhí)行任務
? ? [self performSelector:@selector(run2)onThread:self.thread withObject:nil waitUntilDone:NO];
}
-(void)run2
{
?? ?NSLog(@"----run2------");
}
經(jīng)過運行測試,除了之前打印的----run1-----踊挠,每當我們點擊屏幕乍桂,都能調用----run2------。
這樣我們就實現(xiàn)了常駐線程的需求效床。
作者:進擊的阿牛哥
鏈接:http://www.reibang.com/p/f47ec06097ef
來源:簡書
著作權歸作者所有睹酌。商業(yè)轉載請聯(lián)系作者獲得授權,非商業(yè)轉載請注明出處剩檀。