原因在于滑動(dòng)時(shí)當(dāng)前線程的runloop切換了mode用于列表滑動(dòng),導(dǎo)致timer暫停。
runloop中的mode主要用來指定事件在runloop中的優(yōu)先級(jí),有以下幾種:
Default(NSDefaultRunLoopMode):默認(rèn),一般情況下使用;
Connection(NSConnectionReplyMode):一般系統(tǒng)用來處理NSConnection相關(guān)事件,開發(fā)者一般用不到;
Modal(NSModalPanelRunLoopMode):處理modal panels事件;
Event Tracking(NSEventTrackingRunLoopMode):用于處理拖拽和用戶交互的模式。
Common(NSRunloopCommonModes):模式合集。默認(rèn)包括Default,Modal,Event Tracking三大模式,可以處理幾乎所有事件。
回到題中的情境?;瑒?dòng)列表時(shí),runloop的mode由原來的Default模式切換到了Event Tracking模式,timer原來好好的運(yùn)行在Default模式中,被關(guān)閉后自然就停止工作了。
解決方法其一是將timer加入到NSRunloopCommonModes中。其二是將timer放到另一個(gè)線程中,然后開啟另一個(gè)線程的runloop,這樣可以保證與主線程互不干擾,而現(xiàn)在主線程正在處理頁面滑動(dòng)。示例代碼如下:
// 方法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];
});