Objective-C Basics
- 以scheduledTimerWithTimeInterval的方式觸發的timer,在滑動頁面上的列表時,timer會暫停,為什么?該如何解決?
原因在于滑動時當前線程的runloop切換了mode用于列表滑動,導致timer暫停。
runloop中的mode主要用來指定事件在runloop中的優先級,有以下幾種:
- Default(NSDefaultRunLoopMode):默認,一般情況下使用;
- Connection(NSConnectionReplyMode):一般系統用來處理NSConnection相關事件,開發者一般用不到;
- Modal(NSModalPanelRunLoopMode):處理modal panels事件;
- Event Tracking(NSEventTrackingRunloopMode):用于處理拖拽和用戶交互的模式。
- Common(NSRunLoopCommonModes):模式合集。默認包括Default,Modal,Event Tracking三大模式,可以處理幾乎所有事件。
回到題中的情境。滑動列表時,runloop的mode由原來的Default模式切換到了Event Tracking模式,timer原來好好地運行在Default模式中,被關閉后自然就停止工作了。
解決方法其一是講timer加入到NSRunLoopCommonModes中。其二是將timer放到另一個線程中,然后開啟另一個線程的runloop,這樣可以保證與主線程互不干擾,而現在主線程正在處理頁面滑動。示例代碼如下:
* // 方法1
* [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
*
* // 方法2
* dispatch_async(dispatch_get_global_queue(0, 0), ^{
* timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(repeat:) userInfo:nil repeats:true];
* [[NSRunLoop currentRunLoop] run];
* });
上一題 | 目錄 | 下一題 |
---|