在使用NSTimer時(shí)英妓,比較常見(jiàn)的問(wèn)題:比如,如何初始化绍赛,兩個(gè)初始化方法有什么不同蔓纠?為什么我的NSTimer只執(zhí)行了一次?為什么計(jì)時(shí)器會(huì)因?yàn)榛瑒?dòng)暫停吗蚌?
1)腿倚,初始化的兩個(gè)常用方法:timerWithTimeInterval和scheduledTimerWithTimeInterval
????a)timerWithTimeInterval不會(huì)加到默認(rèn)的RunLoop中,所以不會(huì)執(zhí)行蚯妇,需要自己調(diào)用:
????????[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [[NSRunLoop currentRunLoop] run]; //子線程中務(wù)必調(diào)用
? ? ? ? 這里注意敷燎,如果是在主線程中,那么不需要后面的run方法箩言,因?yàn)橹骶€程的RunLoop一直在運(yùn)行硬贯,過(guò)了一個(gè)timeInterval之后就會(huì)執(zhí)行了。但是在子線程中陨收,runloop沒(méi)有run起來(lái)饭豹,addTimer之后就結(jié)束,資源被收回了务漩,所以不會(huì)執(zhí)行墨状。
????b)scheduledTimerWithTimeInterval會(huì)加到NSDefaultRunLoopMode中。所以:
? ? ? ? scheduledTimerWithTimeInterval = timerWithTimeInterval + [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]
? ? ? ? 同上菲饼,子線程中也要自己來(lái)RunLoop run,否則也是不會(huì)執(zhí)行的列赎。
? ? 2)宏悦,有時(shí)發(fā)現(xiàn)Timer雖然設(shè)置了repeats為YES,但是不執(zhí)行包吝,即使調(diào)用了fire也是只執(zhí)行了一次饼煞。可能的原因就是在子線程中調(diào)用了诗越,參見(jiàn)上一條砖瞧。即RunLoop沒(méi)有run,timer還沒(méi)執(zhí)行代碼塊就結(jié)束被回收了嚷狞。所以這里要主動(dòng)調(diào)用RunLoop run块促。
3)荣堰,ScrollView等控件滾動(dòng)的過(guò)程中會(huì)暫停。直接原因就是Timer的RunLoopMode不對(duì)竭翠,在NSDefaultRunLoopMode中的Timer會(huì)因?yàn)镽unLoop切換Mode導(dǎo)致暫停振坚。ScrollView滾動(dòng)過(guò)程中會(huì)因?yàn)閙ode的切換,而導(dǎo)致NSTimer將不再被調(diào)度斋扰。
ScrollView滾動(dòng)過(guò)程中NSDefaultRunLoopMode(kCFRunLoopDefaultMode)的mode會(huì)切換到UITrackingRunLoopMode來(lái)保證ScrollView的流暢滑動(dòng)渡八,NSTimer就暫停了。
RunLoop只能運(yùn)行在一種mode下传货,如果要換mode屎鳍,當(dāng)前的loop也需要停下重啟成新的。利用這個(gè)機(jī)制问裕,ScrollView滾動(dòng)過(guò)程中NSDefaultRunLoopMode(kCFRunLoopDefaultMode)的mode會(huì)切換到UITrackingRunLoopMode來(lái)保證ScrollView的流暢滑動(dòng):只能在NSDefaultRunLoopMode模式下處理的事件會(huì)影響ScrollView的滑動(dòng)逮壁。
所以,不要使用scheduledTimerWithTimeInterval初始化僻澎,用timerWithTimeInterval初始化貌踏,然后
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];