IOS開發中滑動頁面時NSTimer停止的問題


我們在做倒計時的時候,發現當你手指按着屏幕不放,拖動tableView滑動的時候,寫在cell上得倒計時停止倒計時,松開繼續倒計時。研究發現就是拖動tableView滑動時,NSTimer停止了。

這其實就是runloop的mode在做怪。
runloop可以理解為cocoa下的一種消息循環機制,用來處理各種消息事件,我們在開發 的時候並不需要手動去創建一個runloop,因為框架為我們創建了一個默認的runloop,通過[NSRunloop currentRunloop]我們可以得到一個當前線程下面對應的runloop對象,不過我們需要注意的是不同的runloop之間消息的通知方式。

接着上面的話題,在開啟一個NSTimer實質上是在當前的runloop中注冊了一個新的事件源,而當scrollView滾動的時候,當前的 MainRunLoop是處於UITrackingRunLoopMode的模式下,在這個模式下,是不會處理NSDefaultRunLoopMode 的消息(因為RunLoop Mode不一樣),要想在scrollView滾動的同時也接受其它runloop的消息,我們需要改變兩者之間的runloopmode.

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

簡單的說就是NSTimer不會開啟新的進程,只是在Runloop里注冊了一下,Runloop每次loop時都會檢測這個timer,看是否可 以觸發。當Runloop在A mode,而timer注冊在B mode時就無法去檢測這個timer,所以需要把NSTimer也注冊到A mode,這樣就可以被檢測到。

一個簡單例子,創建NSTimer進行倒計時時,修改model:

- (id)initWithTimeout:(NSInteger)total {
    if (self = [self init]) {
        self.counter = total;
        if (total > 0) {
            self.countdown = YES;
            // Notice: scheduledTimerWithTimeInterval adds the timer to the current thread's run loop
            timer = [NSTimer scheduledTimerWithTimeInterval:1
                                                     target:self
                                                   selector:@selector(countingDown:)
                                                   userInfo:nil
                                                    repeats:YES];
            
            [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
            return self;
        }
    }
    
    return self;
}

 

說到這里,在http異步通信的模塊中也有可能碰到這樣的問題,就是在向服務器異步獲取圖片數據通知主線程刷新tableView中的圖片時,在 tableView滾動沒有停止或用戶手指停留在屏幕上的時候,圖片一直不會出來,可能背后也是這個runloop的mode在做怪。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM