1. 程式人生 > >RunLoop五:在實際開發中的應用

RunLoop五:在實際開發中的應用

一、在實際開發中的應用

  • 控制執行緒生命週期(執行緒保活)
  • 解決NSTimer在滑動時停止工作的問題
  • 監控應用卡頓
  • 效能優化

二、控制執行緒生命週期(執行緒保活)
在專案中會遇到建立一個子執行緒去做一些事情。為什麼要建立一個子執行緒去做事情?因為如果把所有的事情都放在主執行緒中去做,就會阻塞住組執行緒。導致APP 看起來很卡。這個時候就可以開啟一個子執行緒,把耗時的操作放到子執行緒中。這樣就不會阻塞主執行緒,APP 開起來不會卡。
子執行緒做完事情以後,就會銷燬。但有的時候,希望子執行緒昨晚事情以後,不要銷燬,當程式設計師需要的時候才銷燬。這個時候就可以使用 RunLoop 控制子執行緒的生命週期。
這種做法也叫做執行緒保活(保住執行緒的命)。

三、解決NSTimer在滑動時停止工作的問題
(一)、為什麼 NSTimer 不能再滾動 UIScrollView時保持開啟狀態

  • 預設情況下,在滾動 tableView、UIScrollView 的時候。NSTimer會停止工作。

  • 建立一個 UITextView, UITextView 是 UIScrollView 的子類。使用它來演示 NSTimer 在滑動時停止工作的問題

  • 寫一個 定時器程式碼,每隔一秒鐘列印一次
    定時器程式碼,每隔一秒鐘列印一次

  • 當滾動 UITextView 的時候,定時器停止列印。這是因為 混動 UITextView 的時候,RunLoop 會進入另一個Mode 模式UITrackingRunLoopMode 下.

  • 當在UITrackingRunLoopMode模式下,定時器會停止。

  • 當不在滾動 UITextView , 定時器會重新開始。
    在這裡插入圖片描述

  • 這是因為 RunLoop 同一時間,只能執行一種模式。當滾動UITextView 的時候,定時器會停止。說明這兩個模式不一樣。也就是說 NSTimer 不是 UITrackingRunLoopMode 模式。

  • NSTimer 是在預設模式下工作的。kCFRunLoopDefaultMode模式

  • 也可以使用 CFRunLoopCopyCurrentMode(CFRunLoopGetCurrent()) 列印一下當前的 模式

注:

  • kCFRunLoopDefaultMode(NSDefaultRunLoopMode):App的預設Mode,通常主執行緒是在這個Mode下執行
  • UITrackingRunLoopMode:介面跟蹤 Mode,用於 ScrollView 追蹤觸控滑動,保證介面滑動時不受其他 Mode 影響

(二)、讓 NSTimer 在 滾動 UIScrollView時也可以滾動

  • 方法[NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) { ... ... }]; 會直接把定時器新增到 預設mode中
  • 方法 [NSTimer timerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) { ... ... }]; 只是返回一個 NSTimer 中。沒有新增到 runloop 中.
  • [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; 把 timer 新增到 runloop 中。 forMode 後面可以新增三種:
    • NSDefaultRunLoopMode : 預設模式
    • UITrackingRunLoopModes: UIScrollView 的那種模式
    • NSRunLoopCommonModes: 通用模式 。
      • 它並不是一個真的模式,它只是一個標記
      • 上面的 NSDefaultRunLoopMode 和 UITrackingRunLoopModes 才是 真正存在的模式
      • 傳入這個 ,意味著:timer 在設定了 common 標記的模式下都能執行。而 NSDefaultRunLoopMode 和 UITrackingRunLoopModes 都標記成了 Common 。 所以在這兩個mode 上都可以使用。

(三)、回顧 RunLoop 的定義

  • RunLoop 的結構

    • 執行緒(pthread_t _pthread): 一個 RunLoop 有一個執行緒 。 一對一。
    • 模式(CFMutableSetRef _modes): 裡面裝著 RunLoop 能用的模式. 有很多個
    • 當前模式(CFRunLoopModeRef _currentMode)
    • CFMutableSetRef _commonModes: 裝到這裡的模式,意味著標記成了 common 的模式。
    • CFMutableSetRef _commonModeItems: 存放能在_commonModes 下工作的 東西(如剛才的 timer 變數)
  • 當呼叫 [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonMode]; 程式碼時,它呼叫的就是 runloop 中的 CFMutableSetRef _commonModes.。

  • 這個common模式下包含 NSDefaultRunLoopMode 和 UITrackingRunLoopModes 這兩個模式。

  • 所以 timer 能在 _commonModes 陣列中存放的模式下工作。
    RunLoop 的結構

四、監控應用卡頓

五、效能優化