iOS 常見面試題--runloop

一帖蔓、什么是runloop

顧名思義就是運(yùn)行循環(huán)丘侠,在程序運(yùn)行過程中循環(huán)做一些事情

二、runloop的基本作用

1炼杖、保持程序的持續(xù)運(yùn)行
2灭返、處理App中的各種事件(比如觸摸事件、定時(shí)器事件等)
3坤邪、節(jié)省CPU資源熙含,提高程序性能:該做事時(shí)做事,該休息時(shí)休息
......

三艇纺、應(yīng)用范疇

1怎静、定時(shí)器(Timer)、PerformSelector
2黔衡、GCD Async Main Queue
3蚓聘、事件響應(yīng)、手勢(shì)識(shí)別盟劫、界面刷新
4夜牡、網(wǎng)絡(luò)請(qǐng)求
5、AutoreleasePool
......

四侣签、獲取runloop對(duì)象

1氯材、OC方法
[NSRunLoop currentRunLoop]; // 獲得當(dāng)前線程的RunLoop對(duì)象
[NSRunLoop mainRunLoop]; // 獲得主線程的RunLoop對(duì)象

2、C語言方法
CFRunLoopGetCurrent(); // 獲得當(dāng)前線程的RunLoop對(duì)象
CFRunLoopGetMain(); // 獲得主線程的RunLoop對(duì)象

五硝岗、RunLoop相關(guān)的類

CFRunLoopRef
CFRunLoopModeRef
CFRunLoopSourceRef
CFRunLoopTimerRef
CFRunLoopObserverRef

CFRunLoopRef

內(nèi)部底層結(jié)構(gòu) 

typedef struct __CFRunloop * CFRunLoopRef;
struct __CFRunloop{
 pthread_ _t_ pthread;//線程
CFMutableSetRef_ commonModes ;
CFMutableSetRef_ commonModeItems ;
CFRunLoopModeRef_ currentMode ;//當(dāng)前模式
CFMutableSetRef_ modes;//模式數(shù)組(里面存放好多模式 模式類型為CFRunLoopModeRef)
}

CFRunLoopModeRef

內(nèi)部底層結(jié)構(gòu)

typedef struct__ CFRunLoopMode *CFRunLoopModeRef ;
struct __CFRunLoopMode{
CFStringRef  _name ;//模式名稱
CFMutableSetRef  _ sources0; (內(nèi)部存放CFRunLoopSourceRef 類型的對(duì)象 )
CFMutableSetRef  _ sources1 ;(內(nèi)部存放CFRunLoopSourceRef 類型的對(duì)象 )
CFMutableArrayRef  _ observers;(內(nèi)部存放CFRunLoopObserverRef 類型的對(duì)象 )
CFMutableArrayRef  _ timers;(內(nèi)部存放CFRunLoopTimerRef 類型的對(duì)象 )
}


相關(guān)說明
1、CFRunLoopModeRef代表RunLoop的運(yùn)行模式
2袋毙、一個(gè)RunLoop包含若干個(gè)Mode型檀,每個(gè)Mode又包含若干Source0/Source1/Timer/Observer
3、RunLoop啟動(dòng)時(shí)只能選擇其中一個(gè)Mode听盖,作為currentMode
4胀溺、如果需要切換Mode,只能退出當(dāng)前mode皆看,再重新選擇一個(gè)Mode進(jìn)入仓坞,
(作用: 不同組的Source0/Source1/Timer/Observer能分隔開來,互不影響)
5腰吟、如果Mode里沒有任何Source0/Source1/Timer/Observer无埃,RunLoop會(huì)立馬退出



常見的2種Mode

1、kCFRunLoopDefaultMode(NSDefaultRunLoopMode):App的默認(rèn)Mode毛雇,通常主線程是在這個(gè)Mode下運(yùn)行

2嫉称、UITrackingRunLoopMode:界面跟蹤 Mode,用于 ScrollView 追蹤觸摸滑動(dòng)灵疮,保證界面滑動(dòng)時(shí)不受其他 Mode 影響




CFRunLoopObserverRef

/* Run Loop Observer Activities */
typedef CF_ OPTIONS (CFOptionFlags, CFRunLoopActivity) {
kCFRunLoopEntry = (1UL << 0) ,                       //即將進(jìn)入Loop
kCFRunLoopBeforeTimers = (1UL << 1)织阅,       // 即將處理Timer
kCFRunLoopBeforeSources = (1UL << 2) ,      //即將處理Source
kCFRunLoopBeforeWaiting = (1UL << 5) ,        // 即將進(jìn)入休眠 ,
kCFRunLoopAfterWaiting = (1UL << 6) ,          / /剛從休眠中喚醒
kCFRunLoopExit = (1UL << 7)震捣,                       //即將退出Loop
kCFRunL oopAllActivities = 0x0FFFFFFFU       //所有狀態(tài)集合
};


我們可以利用  CFRunLoopObserverRef  來監(jiān)聽runloop 的各種狀態(tài):(如刷新UI等等)
    // 創(chuàng)建Observer
    CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
        switch (activity) {
            case kCFRunLoopEntry: {
                CFRunLoopMode mode = CFRunLoopCopyCurrentMode(CFRunLoopGetCurrent());
                NSLog(@"kCFRunLoopEntry - %@", mode);
                CFRelease(mode);
                break;
            }
                
            case kCFRunLoopExit: {
                CFRunLoopMode mode = CFRunLoopCopyCurrentMode(CFRunLoopGetCurrent());
                NSLog(@"kCFRunLoopExit - %@", mode);
                CFRelease(mode);
                break;
            }
                
            default:
                break;
        }
    });
    // 添加Observer到RunLoop中
    CFRunLoopAddObserver(CFRunLoopGetMain(), observer, kCFRunLoopCommonModes);
    // 釋放
    CFRelease(observer);

六荔棉、RunLoop的運(yùn)行邏輯

Source0 作用
1闹炉、觸摸事件處理
2、performSelector:onThread:

Source1 作用
1润樱、基于Port的線程間通信
2渣触、系統(tǒng)事件捕捉

Timers 作用
1、NSTimer
2祥国、performSelector:withObject:afterDelay:

Observers 作用
1昵观、用于監(jiān)聽RunLoop的狀態(tài) 

根據(jù)runloop的狀態(tài)來做相應(yīng)的事情 如:UI刷新(BeforeWaiting)、Autorelease pool(BeforeWaiting)等

流程
01舌稀、通知Observers:進(jìn)入Loop
02啊犬、通知Observers:即將處理Timers
03、通知Observers:即將處理Sources
04壁查、處理Blocks
05觉至、處理Source0(可能會(huì)再次處理Blocks)
06、如果存在Source1睡腿,就跳轉(zhuǎn)到第8步
07语御、通知Observers:開始休眠(等待消息喚醒)
08、通知Observers:結(jié)束休眠(被某個(gè)消息喚醒)
    01> 處理Timer
    02> 處理GCD Async To Main Queue
    03> 處理Source1
09席怪、處理Blocks
10应闯、根據(jù)前面的執(zhí)行結(jié)果,決定如何操作
    01> 回到第02步
    02> 退出Loop
11挂捻、通知Observers:退出Loop

七碉纺、runloop與線程之間的關(guān)系

1、每條線程都有唯一的一個(gè)與之對(duì)應(yīng)的RunLoop對(duì)象
2刻撒、RunLoop保存在一個(gè)全局的Dictionary里骨田,線程作為key,RunLoop作為value
3声怔、線程剛創(chuàng)建時(shí)并沒有RunLoop對(duì)象态贤,RunLoop會(huì)在第一次獲取它時(shí)創(chuàng)建([NSRunLoop currentRunLoop])
4、RunLoop會(huì)在線程結(jié)束時(shí)銷毀
5醋火、主線程的RunLoop已經(jīng)自動(dòng)獲扔破(創(chuàng)建),子線程默認(rèn)沒有開啟RunLoop

面試題1芥驳、講講 RunLoop介粘,項(xiàng)目中有用到嗎?

答:肯定是有用到的 例如下
1晚树、控制線程生命周期(線程币霾桑活)
2、解決NSTimer在滑動(dòng)時(shí)停止工作的問題
3、監(jiān)控應(yīng)用卡頓
4慨亲、性能優(yōu)化

面試題2婚瓜、runloop內(nèi)部實(shí)現(xiàn)邏輯?

第一步:首先通知Observers進(jìn)入Loop 然后處理一些 定時(shí)器刑棵、事件巴刻、block
第二步:事件處理完成之后通知Observers進(jìn)入休眠狀態(tài)開始休眠 等待消息喚醒
第三步:通知Observers結(jié)束休眠處理一些 定時(shí)器、事件蛉签、block

面試題3胡陪、runloop和線程的關(guān)系?

一對(duì)一關(guān)系
1碍舍、每條線程都有唯一的一個(gè)與之對(duì)應(yīng)的RunLoop對(duì)象
2柠座、RunLoop保存在一個(gè)全局的Dictionary里,線程作為key片橡,RunLoop作為value
3妈经、線程剛創(chuàng)建時(shí)并沒有RunLoop對(duì)象,RunLoop會(huì)在第一次獲取它時(shí)創(chuàng)建([NSRunLoop currentRunLoop])
4捧书、RunLoop會(huì)在線程結(jié)束時(shí)銷毀
5吹泡、主線程的RunLoop已經(jīng)自動(dòng)獲取(創(chuàng)建)经瓷,子線程默認(rèn)沒有開啟RunLoop

面試題4爆哑、timer 與 runloop 的關(guān)系?

一個(gè)runloop下會(huì)包含很多個(gè)model,每個(gè)model下又會(huì)包含很多的timer/source/observe舆吮,同一時(shí)刻runloop只能在一種模式下運(yùn)行泪漂,處理一種模式下的狀態(tài)
所以層次關(guān)系是    runloop 包含 model 包含 timer/source/observe   

面試題5、程序中添加每3秒響應(yīng)一次的NSTimer歪泳,當(dāng)拖動(dòng)tableview時(shí)timer可能無法響應(yīng)要怎么解決?

runloop 常用的mode有兩種 :NSDefaultRunLoopMode露筒、UITrackingRunLoopMode
程序默認(rèn)處于 NSDefaultRunLoopMode 模式下  但是頁面滑動(dòng)的時(shí)候 runloop的模式就會(huì)切換到 UITrackingRunLoopMode 此時(shí)就會(huì)退出 NSDefaultRunLoopMode 呐伞,在NSDefaultRunLoopMode模式下所有的操作都會(huì)被停止(如:NSTimer事件響應(yīng))。當(dāng)頁面停止滑動(dòng)時(shí) 就會(huì)自動(dòng)切換到NSDefaultRunLoopMode慎式,(此時(shí)NSTimer才會(huì)繼續(xù)工作 )

因此:想要在當(dāng)拖動(dòng)tableview時(shí)timer繼續(xù)工作 就必須把 timer 添加到runloop任何模式都能工作伶氢。代碼如下
 [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

NSRunLoopCommonModes:并不是一個(gè)真的模式,它只是一個(gè)標(biāo)記



面試題6瘪吏、runloop 是怎么響應(yīng)用戶操作的癣防, 具體流程是什么樣的?

首先由Source1捕捉系統(tǒng)事件  然后Source1又將事件存放在 事件隊(duì)列中交給Source0來處理掌眠。

面試題7蕾盯、說說runLoop的幾種狀態(tài)

一共有6中狀態(tài):
1、kCFRunLoopEntry = (1UL << 0) ,                       //即將進(jìn)入Loop
2蓝丙、kCFRunLoopBeforeTimers = (1UL << 1)级遭,       // 即將處理Timer
3望拖、kCFRunLoopBeforeSources = (1UL << 2) ,      //即將處理Source
4、kCFRunLoopBeforeWaiting = (1UL << 5) ,        // 即將進(jìn)入休眠 挫鸽,
5说敏、kCFRunLoopAfterWaiting = (1UL << 6) ,          / /剛從休眠中喚醒
6、kCFRunLoopExit = (1UL << 7)丢郊,                       //即將退出Loop

面試題8盔沫、runloop的mode作用是什么?

常見的mode有兩種  NSDefaultRunLoopMode和UITrackingRunLoopMode
1枫匾、kCFRunLoopDefaultMode(NSDefaultRunLoopMode):App的默認(rèn)Mode架诞,通常主線程是在這個(gè)Mode下運(yùn)行

2、UITrackingRunLoopMode:界面跟蹤 Mode婿牍,用于 ScrollView 追蹤觸摸滑動(dòng)侈贷,保證界面滑動(dòng)時(shí)不受其他 Mode 影響
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市等脂,隨后出現(xiàn)的幾起案子俏蛮,更是在濱河造成了極大的恐慌,老刑警劉巖上遥,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件搏屑,死亡現(xiàn)場離奇詭異,居然都是意外死亡粉楚,警方通過查閱死者的電腦和手機(jī)辣恋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來模软,“玉大人伟骨,你說我怎么就攤上這事∪家欤” “怎么了携狭?”我有些...
    開封第一講書人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長回俐。 經(jīng)常有香客問我逛腿,道長,這世上最難降的妖魔是什么仅颇? 我笑而不...
    開封第一講書人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任单默,我火速辦了婚禮,結(jié)果婚禮上忘瓦,老公的妹妹穿的比我還像新娘搁廓。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開白布枚抵。 她就那樣靜靜地躺著线欲,像睡著了一般。 火紅的嫁衣襯著肌膚如雪汽摹。 梳的紋絲不亂的頭發(fā)上李丰,一...
    開封第一講書人閱讀 51,165評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音逼泣,去河邊找鬼趴泌。 笑死,一個(gè)胖子當(dāng)著我的面吹牛拉庶,可吹牛的內(nèi)容都是我干的嗜憔。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼氏仗,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼吉捶!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起皆尔,我...
    開封第一講書人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤呐舔,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后慷蠕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體珊拼,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年流炕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了澎现。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡每辟,死狀恐怖剑辫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情渠欺,我是刑警寧澤妹蔽,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站峻堰,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏盅视。R本人自食惡果不足惜捐名,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望闹击。 院中可真熱鬧镶蹋,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至拂酣,卻和暖如春秋冰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背婶熬。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來泰國打工剑勾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人赵颅。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓虽另,卻偏偏與公主長得像,于是被迫代替她去往敵國和親饺谬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子捂刺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容