NSRunloop小总结
生活随笔
收集整理的這篇文章主要介紹了
NSRunloop小总结
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
一、概述
1.Run loops是線程的基礎(chǔ)架構(gòu)部分。一個run loop就是一個事件處理循環(huán),用來不停的調(diào)配工作以及處理輸入事件。使用run loop的目的是使你的線程在有工作的時候工作,沒有的時候休眠。
2.Run loop的管理并不完全是自動的。你仍必須設(shè)計你的線程代碼以在適當(dāng)?shù)臅r候啟動run loop并正確響應(yīng)輸入事件。Cocoa和CoreFundation都提供了run loop對象方便配置和管理線程的run loop。你創(chuàng)建的程序不需要顯示的創(chuàng)建run loop;任何線程,包含程序的主線程(main thread)都有與之相應(yīng)的run loop對象。但是,自己創(chuàng)建的次線程是需要手動運行run loop的。在carbon和cocoa程序中,程序啟動時,主線程會自行創(chuàng)建并運行run loop。
3.Run loop處理的輸入事件有兩種不同的來源:輸入源(input source)和定時源(timer source)。輸入源傳遞異步消息,通常來自于其他線程或者程序。定時源則傳遞同步消息,在特定時間或者一定的時間間隔發(fā)生。除了處理輸入源,run loop也會生成關(guān)于run loop行為的notification。注冊的run-loop 觀察者可以收到這些notification,并做相應(yīng)的處理。可以使用Core Foundation在你的線程注冊run-loop觀察者。
二、Run Loop Modes
1.Run loop模式是所有要監(jiān)視的輸入源和定時源以及要通知的注冊觀察者的集合。每次運行run loop都會指定其運行在哪個模式下。以后,只有相應(yīng)的源會被監(jiān)視并允許接收他們傳遞的消息。(類似的,只有相應(yīng)的觀察者會收到通知)。其他模式關(guān)聯(lián)的源只有在run loop運行在其模式下才會運行,否則處于暫停狀態(tài)。
2.通常代碼中通過指定名字來確定模式。Cocoa和core foundation定義了默認(rèn)的以及一系列常用的模式,都是用字符串來標(biāo)識。當(dāng)然你也可以指定字符串來自定義模式。雖然你可以給模式指定任何名字,但是所有的模式內(nèi)容都是相同的。你必須添加輸入源,定時器或者run loop觀察者到你定義的模式中。
3.通過指定模式可以使得run loop在某一階段只關(guān)注感興趣的源。大多數(shù)時候,run loop都是運行在系統(tǒng)定義的默認(rèn)模式。但是模態(tài)面板(modal panel)可以運行在 “模態(tài)”模式下。在這種模式下,只有和模態(tài)面板相關(guān)的源可以傳遞消息給線程。對于次線程,可以使用自定義模式處理時間優(yōu)先的操作,即屏蔽優(yōu)先級低的源傳遞消息。
4.Note:模式區(qū)分基于事件的源而非事件的種類。例如,你不可以使用模式只選擇處理鼠標(biāo)按下或者鍵盤事件。你可以使用模式監(jiān)聽端口, 暫停定時器或者其他對源或者run loop觀察者的處理,只要他們在當(dāng)前模式下處于監(jiān)聽狀態(tài)。
三、Run Loop Modes列表(由蘋果官方文檔翻譯而來)
1.NSDefaultRunLoopMode:大多數(shù)操作使用的默認(rèn)模式,多數(shù)情況下你需要使用這個模式來開啟你的run loop以及配置輸入源。?NSTimer默認(rèn)是使用這個模式部署的。
2.NSConnectionReplyMode:Cocoa使用這個模式來關(guān)聯(lián)NSConnection去監(jiān)聽返回,你應(yīng)該很少會使用這個模式。
3.NSModalPanelRunLoopMode:Cocoa使用這個模式來鑒定模態(tài)面板的時間目的。很少使用。
4.NSEventTrackingRunLoopMode:當(dāng)有鼠標(biāo)操作或者其它用戶跟蹤交互時,Cocoa使用這個模式去限制其它輸入事件。
5.NSRunLoopCommonModes:這是一個可配置的通用的模式組合,當(dāng)將一個輸入源跟這個模式關(guān)聯(lián),輸入源將會和組合里面的所有模式關(guān)聯(lián)。在Cocoa applications(主線程)中,這個組合默認(rèn)包含Default,Modal,以及eventTrack。在Core Foundation(子線程)中,默認(rèn)只包含default。可以通過CFRunLoopAddCommonMode來配置這個組合。
四、使用中遇到的問題:
1.問題一:(1)場景說明:在一個ios應(yīng)用中,使用NSTimer的默認(rèn)方式(NSDefaultRunLoopMode模式下)初始化了一個定時器,或者以NSDefaultRunLoopMode方式在RunLoop上部署了網(wǎng)絡(luò)請求(沒有使用[connection scheduleInRunLoopXXXX]方法,默認(rèn)都是Default),而此時發(fā)生了用戶交互,例如發(fā)生了ScrollView滾動,此時主線程的RunLoop處在NSEventTrackingRunLoopMode模式下,其它的輸入事件將會被屏蔽掉,導(dǎo)致定時器任務(wù)沒有執(zhí)行或者收不到網(wǎng)絡(luò)請求回調(diào)。(2)具體測試情況:(當(dāng)用手一直滾動ScrollView或者手指不起來) <1>Timer:Timer的觸法會被直接過濾掉,調(diào)用不會堆積。 <2>Connection:請求回調(diào)會收不到,短時間內(nèi)停止交互,數(shù)據(jù)不會丟失,數(shù)據(jù)會累積等回調(diào)發(fā)生時一起返回,但是如果長時間不停止交互,請求會超時或者鏈接丟失。非用戶主動發(fā)起的交互不會阻塞回調(diào),例如通過代碼自動發(fā)起的UI動畫。(3)解決辦法:在此種情況下,需要將定時器或者網(wǎng)絡(luò)請求以NSRunLoopCommonModes模式部署到RunLoop上,這樣用戶交互事件和其它輸入事件就可以同時接收了。例如:[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];[connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
2.問題二:(1)場景說明:在子線程中去發(fā)送異步請求,默認(rèn)情況下收不到請求回調(diào)。(2)解決辦法:子線程有自動創(chuàng)建RunLoop,但是默認(rèn)是沒有運行的,在開始發(fā)送網(wǎng)絡(luò)請求后,需要手動啟動子線程的RunLoop,才能接收輸入事件,并受到反饋。代碼如下:[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
1.Run loops是線程的基礎(chǔ)架構(gòu)部分。一個run loop就是一個事件處理循環(huán),用來不停的調(diào)配工作以及處理輸入事件。使用run loop的目的是使你的線程在有工作的時候工作,沒有的時候休眠。
2.Run loop的管理并不完全是自動的。你仍必須設(shè)計你的線程代碼以在適當(dāng)?shù)臅r候啟動run loop并正確響應(yīng)輸入事件。Cocoa和CoreFundation都提供了run loop對象方便配置和管理線程的run loop。你創(chuàng)建的程序不需要顯示的創(chuàng)建run loop;任何線程,包含程序的主線程(main thread)都有與之相應(yīng)的run loop對象。但是,自己創(chuàng)建的次線程是需要手動運行run loop的。在carbon和cocoa程序中,程序啟動時,主線程會自行創(chuàng)建并運行run loop。
3.Run loop處理的輸入事件有兩種不同的來源:輸入源(input source)和定時源(timer source)。輸入源傳遞異步消息,通常來自于其他線程或者程序。定時源則傳遞同步消息,在特定時間或者一定的時間間隔發(fā)生。除了處理輸入源,run loop也會生成關(guān)于run loop行為的notification。注冊的run-loop 觀察者可以收到這些notification,并做相應(yīng)的處理。可以使用Core Foundation在你的線程注冊run-loop觀察者。
二、Run Loop Modes
1.Run loop模式是所有要監(jiān)視的輸入源和定時源以及要通知的注冊觀察者的集合。每次運行run loop都會指定其運行在哪個模式下。以后,只有相應(yīng)的源會被監(jiān)視并允許接收他們傳遞的消息。(類似的,只有相應(yīng)的觀察者會收到通知)。其他模式關(guān)聯(lián)的源只有在run loop運行在其模式下才會運行,否則處于暫停狀態(tài)。
2.通常代碼中通過指定名字來確定模式。Cocoa和core foundation定義了默認(rèn)的以及一系列常用的模式,都是用字符串來標(biāo)識。當(dāng)然你也可以指定字符串來自定義模式。雖然你可以給模式指定任何名字,但是所有的模式內(nèi)容都是相同的。你必須添加輸入源,定時器或者run loop觀察者到你定義的模式中。
3.通過指定模式可以使得run loop在某一階段只關(guān)注感興趣的源。大多數(shù)時候,run loop都是運行在系統(tǒng)定義的默認(rèn)模式。但是模態(tài)面板(modal panel)可以運行在 “模態(tài)”模式下。在這種模式下,只有和模態(tài)面板相關(guān)的源可以傳遞消息給線程。對于次線程,可以使用自定義模式處理時間優(yōu)先的操作,即屏蔽優(yōu)先級低的源傳遞消息。
4.Note:模式區(qū)分基于事件的源而非事件的種類。例如,你不可以使用模式只選擇處理鼠標(biāo)按下或者鍵盤事件。你可以使用模式監(jiān)聽端口, 暫停定時器或者其他對源或者run loop觀察者的處理,只要他們在當(dāng)前模式下處于監(jiān)聽狀態(tài)。
三、Run Loop Modes列表(由蘋果官方文檔翻譯而來)
1.NSDefaultRunLoopMode:大多數(shù)操作使用的默認(rèn)模式,多數(shù)情況下你需要使用這個模式來開啟你的run loop以及配置輸入源。?NSTimer默認(rèn)是使用這個模式部署的。
2.NSConnectionReplyMode:Cocoa使用這個模式來關(guān)聯(lián)NSConnection去監(jiān)聽返回,你應(yīng)該很少會使用這個模式。
3.NSModalPanelRunLoopMode:Cocoa使用這個模式來鑒定模態(tài)面板的時間目的。很少使用。
4.NSEventTrackingRunLoopMode:當(dāng)有鼠標(biāo)操作或者其它用戶跟蹤交互時,Cocoa使用這個模式去限制其它輸入事件。
5.NSRunLoopCommonModes:這是一個可配置的通用的模式組合,當(dāng)將一個輸入源跟這個模式關(guān)聯(lián),輸入源將會和組合里面的所有模式關(guān)聯(lián)。在Cocoa applications(主線程)中,這個組合默認(rèn)包含Default,Modal,以及eventTrack。在Core Foundation(子線程)中,默認(rèn)只包含default。可以通過CFRunLoopAddCommonMode來配置這個組合。
四、使用中遇到的問題:
1.問題一:(1)場景說明:在一個ios應(yīng)用中,使用NSTimer的默認(rèn)方式(NSDefaultRunLoopMode模式下)初始化了一個定時器,或者以NSDefaultRunLoopMode方式在RunLoop上部署了網(wǎng)絡(luò)請求(沒有使用[connection scheduleInRunLoopXXXX]方法,默認(rèn)都是Default),而此時發(fā)生了用戶交互,例如發(fā)生了ScrollView滾動,此時主線程的RunLoop處在NSEventTrackingRunLoopMode模式下,其它的輸入事件將會被屏蔽掉,導(dǎo)致定時器任務(wù)沒有執(zhí)行或者收不到網(wǎng)絡(luò)請求回調(diào)。(2)具體測試情況:(當(dāng)用手一直滾動ScrollView或者手指不起來) <1>Timer:Timer的觸法會被直接過濾掉,調(diào)用不會堆積。 <2>Connection:請求回調(diào)會收不到,短時間內(nèi)停止交互,數(shù)據(jù)不會丟失,數(shù)據(jù)會累積等回調(diào)發(fā)生時一起返回,但是如果長時間不停止交互,請求會超時或者鏈接丟失。非用戶主動發(fā)起的交互不會阻塞回調(diào),例如通過代碼自動發(fā)起的UI動畫。(3)解決辦法:在此種情況下,需要將定時器或者網(wǎng)絡(luò)請求以NSRunLoopCommonModes模式部署到RunLoop上,這樣用戶交互事件和其它輸入事件就可以同時接收了。例如:[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];[connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
2.問題二:(1)場景說明:在子線程中去發(fā)送異步請求,默認(rèn)情況下收不到請求回調(diào)。(2)解決辦法:子線程有自動創(chuàng)建RunLoop,但是默認(rèn)是沒有運行的,在開始發(fā)送網(wǎng)絡(luò)請求后,需要手動啟動子線程的RunLoop,才能接收輸入事件,并受到反饋。代碼如下:[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
總結(jié)
以上是生活随笔為你收集整理的NSRunloop小总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hash和一致性hash
- 下一篇: 2019年规划