1. 程式人生 > >UITableView滾動時NSTimer不執行

UITableView滾動時NSTimer不執行

解決方法增加timer的runloop模式:

[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode]; 
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

原因分析:

NSTImer的實現時基於runLoop的,而runloop又有以下5種模式,某一時刻只能處理對應模式下的事件。

  • Default模式
    定義:NSDefaultRunLoopMode (Cocoa) kCFRunLoopDefaultMode
     (Core Foundation)
    描述:預設模式中幾乎包含了所有輸入源(NSConnection除外),一般情況下應使用此模式
  • Connection模式
    定義:NSConnectionReplyMode(Cocoa)
    描述:處理NSConnection物件相關事件,系統內部使用,使用者基本不會使用。
  • Modal模式
    定義:NSModalPanelRunLoopMode(Cocoa)
    描述:處理modal panels事件。
  • Event tracking模式
    定義:

    UITrackingRunLoopMode

    (iOS) NSEventTrackingRunLoopMode(cocoa)
    描述:在拖動loop或其他user interface tracking loops時處於此種模式下,在此模式下會限制輸入事件的處理。例如,當手指按住UITableView拖動時就會處於此模式
  • Common模式
    定義:NSRunLoopCommonModes (Cocoa) kCFRunLoopCommonModes (Core Foundation)
    描述:這是一個偽模式,其為一組run loop mode的集合,將輸入源加入此模式意味著在Common Modes中包含的所有模式下都可以處理。在Cocoa應用程式中,預設情況下Common Modes包含default modes,modal modes,event Tracking modes.可使用CFRunLoopAddCommonMode方法想Common Modes中新增自定義modes。

獲取當前執行緒的run loop mode:

NSString* runLoopMode = [[NSRunLoopcurrentRunLoop]currentMode];

NSTimer預設處於NSDefaultRunLoopMode,在沒有滾動時,runloop處於NSDefaultRunLoopMode下,滾動時處於UITrackingRunLoopMode,導      致NSTimer事件源被過濾了,所以不執行,那怎麼辦,只需要給NSTimer再新增一個模式:

[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode]

乾脆就所有模式下都能執行:

[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];