iOS基礎面試題之RunLoop篇

RunLoop是什麼,有什麼做用,如何獲取?

  • 定義
    • RunLoop的實質是一個死循環,用於保證程序的持續運行,只有當程序退出的時候纔會結束(由main函數開啓主線程的RunLoop)
  • 做用
    • 保持程序的持續運行
    • 處理App中的各類事件(觸摸、定時器、Selector事件)
    • 節省CPU資源,提升程序性能(該作事作事,沒事作休息)
  • 獲取方法
    • 使用NSRunLoop(面向對象)或者CFRunLoopRef(底層C語言)

RunLoop的原理

  • RunLoop開啓一個循環事件,並接受輸入事件,接受的事件來自兩種不一樣的來源:
    • 輸入源(input source)(傳遞異步事件)
    • 定時源(timer source)(傳遞同步事件)
  • RunLoop接收到消息後採用handlePort、customSrc、mySelector和timerFired等四個方法處理對應的事件
  • 當RunLoop沒有接收到消息時,則進入休眠狀態,以保持程序持續運行

本人5年iOS開發經驗,曾就任於阿里巴巴。 善於把艱澀的iOS知識轉化爲通俗易懂的白話文字,同時也歡迎你們加入小編的iOS交流羣 834688868 ,羣裏會提供相關面試資料,書籍歡迎你們入駐!面試

image

RunLoop接收幾種輸入源,系統默認定義了幾種模式?

  • 輸入源有兩種
    • 基於端口的輸入源(port)
    • 自定義的輸入源(custom)
  • 系統定義的RunLoop模式有五種,最經常使用的有三種,以下所示:
    • NSDefaultRunLoopMode
      • 默認模式,主線程中默認是NSDefaultRunLoopMode
    • UITrackingRunLoopMode
      • 視圖滾動模式,RunLoop會處於該模式下
    • NSRunLoopCommonModes
      • 並非真正意義上的Mode,是一個佔位用的「Mode」,默認包含了NSDefaultRunLoopMode和UITrackingRunLoopMode兩種模式

RunLoop模式的原理和使用注意點?

  • 原理和注意點
    • 一個RunLoop包含若干個Mode,每一個Mode又包含若干個Source、Observer、Timer(以下圖所示)
    • 每次RunLoop啓動,只能指定一個Mode,這個Mode被稱爲CurrentMode
    • 若是須要切換Mode,只能退出Loop,再從新指定一個Mode進入, 以使不一樣組之間的Source、Observer、Timer互不受影響

image

RunLoop和線程有什麼關係

  • RunLoop與線程是一一對應的
  • 程序啓動時,主線程默認會本身建立RunLoop,並設置爲Default模式
  • 建立子線程時,必須獲取當前線程的RunLoop並啓動它
NSRunLoop *loop = [NSRunLoop currentRunLoop];
[loop run];

複製代碼

NSTimer和RunLoop的關係?

  • NSTimer須要添加到Runloop中, 才能執行的狀況
NSTimer *timer = [NSTimer timerWithTimeInterval:1.f target:self selector:@selector(update) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

複製代碼
  • NSTimer默認被添加到Runloop中, 直接執行的狀況
[NSTimer scheduledTimerWithTimeInterval:1.f target:self selector:@selector(update) userInfo:nil repeats:YES];

複製代碼

NSTimer準確嗎,若是不許確,如何設計一個準確的timer?

  • 不許確
  • 準確的Timer應該和當前線程的RunLoopMode保持一致

TableView/ScrollView/CollectionView滾動時爲何NSTimer會中止?

  • 一個RunLoop不能同時共存兩個mode
  • 當滾動視圖滾動時,當前RunLoop處於UITrackingRunLoopMode,
  • NSTimer的RunLoopMode和當前線程的RunLoopMode不一致,因此會中止
  • 解決方法:將timer的runloopMode改成UITrackingRunLoopMode或者NSRunLoopCommonModes

若是NSTimer在分線程中建立,會發生什麼,應該注意什麼?

  • NSTimer沒有啓動
    • 在主線程中,系統默認建立並啓動主線程的runloop
    • 在分線程中,系統不會自動啓動runloop,須要手動啓動
  • 解決方法:
    • 啓動分線程的runLoop

在異步線程中下載不少圖片,若是失敗了,該如何處理?請結合RunLoop來談談解決方案

  • 在異步線程中啓動一個RunLoop從新發送網絡請求,下載圖片

若是程序啓動就須要執行一個耗時操做,你會怎麼作?

  • 開啓一個異步的子線程,並啓動它的RunLoop來執行該耗時操做

runloop與autoreleasepool的關係

若是在分線程中啓動一個異步請求,會有什麼問題?

判斷其是否請求結束,若是未結束,要保持當前線程一直啓動,直到結束markdown

while(!isFinish)
     {
       [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
     }

複製代碼

程序啓動時,runloop是如何工做的?若是程序啓動就須要執行一個耗時操做,你會怎麼作?

程序啓動時,系統默認建立並啓動主線程的runloop,runloop會默認建立兩個Observe來進行監聽runloop的進出和睡眠,有事情的時候就去作,沒事的休眠網絡

(線程(建立)-->runloop將進入-->最高優先級OB建立釋放池-->runloop將睡-->最低優先級OB銷燬舊池建立新池-->runloop將退出-->最低優先級OB銷燬新池-->線程(銷燬))異步

線程剛建立時並無runloop,若是你不主動去獲取,那麼一直都不會有。函數

耗時操做能夠放在分線程中進行,結束後回到主線程oop

做者:Stars木木 連接:www.jianshu.com/p/848ea3817…性能

相關文章
相關標籤/搜索