在使用NSTimer時,比較常見的問題:比如,如何初始化,兩個初始化方法有什么不同?為什么我的NSTimer只執(zhí)行了一次?為什么計時器會因為滑動暫停?
1),初始化的兩個常用方法:timerWithTimeInterval和scheduledTimerWithTimeInterval
????a)timerWithTimeInterval不會加到默認(rèn)的RunLoop中,所以不會執(zhí)行,需要自己調(diào)用:
????????[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [[NSRunLoop currentRunLoop] run]; //子線程中務(wù)必調(diào)用
? ? ? ? 這里注意,如果是在主線程中,那么不需要后面的run方法,因為主線程的RunLoop一直在運行,過了一個timeInterval之后就會執(zhí)行了。但是在子線程中,runloop沒有run起來,addTimer之后就結(jié)束,資源被收回了,所以不會執(zhí)行。
????b)scheduledTimerWithTimeInterval會加到NSDefaultRunLoopMode中。所以:
? ? ? ? scheduledTimerWithTimeInterval = timerWithTimeInterval + [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]
? ? ? ? 同上,子線程中也要自己來RunLoop run,否則也是不會執(zhí)行的。
? ? 2),有時發(fā)現(xiàn)Timer雖然設(shè)置了repeats為YES,但是不執(zhí)行,即使調(diào)用了fire也是只執(zhí)行了一次。可能的原因就是在子線程中調(diào)用了,參見上一條。即RunLoop沒有run,timer還沒執(zhí)行代碼塊就結(jié)束被回收了。所以這里要主動調(diào)用RunLoop run。
3),ScrollView等控件滾動的過程中會暫停。直接原因就是Timer的RunLoopMode不對,在NSDefaultRunLoopMode中的Timer會因為RunLoop切換Mode導(dǎo)致暫停。ScrollView滾動過程中會因為mode的切換,而導(dǎo)致NSTimer將不再被調(diào)度。
ScrollView滾動過程中NSDefaultRunLoopMode(kCFRunLoopDefaultMode)的mode會切換到UITrackingRunLoopMode來保證ScrollView的流暢滑動,NSTimer就暫停了。
RunLoop只能運行在一種mode下,如果要換mode,當(dāng)前的loop也需要停下重啟成新的。利用這個機(jī)制,ScrollView滾動過程中NSDefaultRunLoopMode(kCFRunLoopDefaultMode)的mode會切換到UITrackingRunLoopMode來保證ScrollView的流暢滑動:只能在NSDefaultRunLoopMode模式下處理的事件會影響ScrollView的滑動。
所以,不要使用scheduledTimerWithTimeInterval初始化,用timerWithTimeInterval初始化,然后
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];