iOS-RunLoop

jopen 8年前發布 | 17K 次閱讀 Cocoa iOS開發 移動開發

RunLoop總結

需要思考問題

為什么程序在使用的時候可以接受用戶的觸摸事件,不使用的時候什么事件都不發生?

查看一下 main.m 文件,這是程序啟動的入口函數。

int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

代碼調用的時候,主線程也開始運行。文檔上說 UIApplicationMain 函數指定了appliacaion的delegate,并且開啟了event cycle。那什么是event cycle?

RunLoop

程序的event cycle其實就是RunLoop,RunLoop在程序啟動的時候就開啟,接受用戶的處理事件。

這是官方文檔上面的一個圖,可以看到RunLoop在線程中循環監聽需要處理的事件。能夠接收兩種不同的事件源

  • Input sources(輸入源):傳遞異步事件。
  • Timer sources(定時器): 傳遞同步事件、發生在特定時間或者重復的時間間隔。

RunLoop Mode

  • Default模式:幾乎包含了所有輸入源,一般情況下使用這個模式

    • NSDefaultRunLoopMode (Cocoa)
    • kCFRunLoopDefaultMode (Core Foundation)
  • Connection模式

    • 處理NSConnection對象相關事件,系統內部使用,用戶基本不會使用。
  • Modal模式
    • 處理modal panels事件
  • Event tracking模式:滑動Scrollview、Tableview的時候就處于這個模式

    • UITrackingRunLoopMode(iOS)
    • NSEventTrackingRunLoopMode(cocoa)
  • Common模式: 模式的組合,所有的模式下都可以處理

    • NSRunLoopCommonModes (Cocoa)
    • kCFRunLoopCommonModes (Core Foundation)

RunLoop與線程的關系

每條線程都有唯一的RunLoop對象與之對應,主線程的RunLoop是自動創建并啟動的。子線程的RunLoop需要手動創建,并且調用 run 方法啟動。 currentRunLoop 是延遲加載的,只創建一次.

[[NSRunLoop currentRunLoop] run];

指定RunLoop運行的模式和過期時間

- (BOOL)runMode:(NSString *)mode beforeDate:(NSDate *)limitDate;

使用場景

1、NSTimer

如果在ScrollView里面使用到NSTimer的,需要調用 addTimer:forMode 方法指定model,才能在滾動的時候生效。

NSTimer創建的定時器因為需要指定model運行,在RunLoop中需要處理各種事件,導致NSTimer不精確。可以使用GCD方法來創建,GCD不受RunLoop的Mode影響.

 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);


    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    // 要搞一個強引用,不然定時器創建出來就掛了
    self.timer = timer;

    // 延遲3秒開始執行
    dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
    // 每隔2秒執行一次
    uint64_t interval = (uint64_t)(2.0 * NSEC_PER_SEC);
    dispatch_source_set_timer(self.timer, start, interval, 0);

    // 要執行的任務
    dispatch_source_set_event_handler(self.timer, ^{
        NSLog(@"%s",__func__);
    });

    // 啟動定時器
    dispatch_resume(self.timer);

    // 停止定時器
dispatch_cancel(self.timer);

2、ImageView的加載

圖片的加載放在 NSDefaultRunLoopMode ,因為ScrollView的滾動是在 UITrackingRunLoopMode 下運行的。

3、PerformSelector指定執行的模式

- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray<NSString *> *)modes;

參考

1、 官方文檔

2、 http://www.cnblogs.com/xuebao/p/4643704.html

來自: http://www.liuchendi.com/2016/01/04/iOS/28_Runloop/

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!