一.線程阻塞問題
1.主線程

(1) NSRunLoopMode : NSDefaultRunLoopMode
控制臺顯示,拖動 UI 期間定時器停止打印.

(2) NSRunLoopMode : NSRunLoopCommonModes?
拖動 UI 期間定時器不停止
總結(jié):主線程的阻塞與 NSRunLoopMode 有關.
2.子線程

此時會阻塞子線程,待 timer 倒計時結(jié)束后才會依次執(zhí)行之后的方法.
(1)拖動 UI 不會阻塞 timer 計時.
(2)與 NSRUNLoopMode 無關.
(3)repeats? 如果設置為 yes,將永遠不會執(zhí)行下面這行代碼.
?NSLog(@"222當前線程:%@",[NSThread currentThread]);
注意: timer 添加到子線程的Runloop 中時,需要啟動 Runloop.
[[NSRunLoop currentRunLoop] run];
二.不能釋放當前對象問題


實際使用 timer 的過程中,我們經(jīng)常會有如下場景.
如果我就是想讓這個 NSTimer 一直輸出,直到 ViewController 銷毀了才停止,我該如何讓它停止呢?
NSTimer 被 Runloop 強引用了,如果要釋放就要調(diào)用 invalidate 方法。
但是我想在 ViewController 的 dealloc 里調(diào)用 invalidate 方法,但是 self 被 NSTimer 強引用了。
所以我還是要釋放 NSTimer 先,然而不調(diào)用 invalidate 方法就不能釋放它。
然而你不進入到 dealloc 方法里我又不能調(diào)用 invalidate 方法。
嗯…
此時 timer 就會一直持有當前對象,當控制器 dismiss 時,并不會執(zhí)行 dealloc 方法, timer 也不會被銷毀.
解決方法:
我們可以造個假的 target 給 NSTimer.這個假的 target 類似于一個中間的代理人,它做的唯一的工作就是挺身而出接下了 NSTimer 的強引用.
參考地址:NSTimer
源碼地址:源碼地址

iOS10之后系統(tǒng)出了如下方法
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
看起來跟文章中給出的方法差不多,但是測試并沒有解決這個問題.