1. NSRunLoopCommonModes和Timer
? 當使用NSTimer的scheduledTimerWithTimeInterval方法時。事實上此時Timer會被加入到當前線程的Run Loop中,且模式是默認的NSDefaultRunLoopMode。而如果當前線程就是主線程,也就是UI線程時,某些UI事件,比如UIScrollView的拖動操作,會將Run Loop切換成NSEventTrackingRunLoopMode模式,在這個過程中,默認的NSDefaultRunLoopMode模式中注冊的事件是不會被執(zhí)行的。也就是說,此時使用scheduledTimerWithTimeInterval添加到Run Loop中的Timer就不會執(zhí)行。
? 所以為了設置一個不被UI干擾的Timer,我們需要手動創(chuàng)建一個Timer,然后使用NSRunLoop的addTimer:forMode:方法來把Timer按照指定模式加入到Run Loop中。這里使用的模式是:NSRunLoopCommonModes,這個模式等效于NSDefaultRunLoopMode和NSEventTrackingRunLoopMode的結(jié)合。(參考Apple文檔)
參考代碼:
- (void)viewDidLoad{
[super viewDidLoad];
NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(timer_callback)userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}
總結(jié):NSTimer默認使用NSDefaultRunLoopMode模式,這種模式的有限級較低,會被tableview的滑動調(diào)用的NSEventTrackingRunLoopMode模式阻礙,導致NSTimer會被等待執(zhí)行。常規(guī)處理方式未[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes],把timer加入到forMode:NSRunLoopCommonModes模式下,這種模式可以和NSEventTrackingRunLoopMode同時執(zhí)行
2.NSTimer的釋放?
首先寫一個錯誤的寫法,怎么定義這是個錯誤呢,就是非常規(guī)寫法.
-(void)dealloc {
[_timer invalidate];
NSLog(@"%@ dealloc", NSStringFromClass([self class]));
}
timer創(chuàng)建
_timer = [NSTimer scheduledTimerWithTimeInterval:3.0f
target:self
selector:@selector(timerFire:)
userInfo:nil
repeats:YES];
把target設置為self,就是在NSRunloop里面強引用了self,也就是說如果這個timer不釋放,那么當前self永遠不會調(diào)用dealloc,通常做法就是在viewwilldiasppera或者 你自己寫的一些釋放方法里面調(diào)用.
題外話:VC的創(chuàng)建是先初始化VC,再初始化VC上的view的父類,再初始化view。釋放的時候順序相反,程序調(diào)用dealloc的時候會這么寫
-(void)dealloc {
}
看著是個空函數(shù),其實上執(zhí)行了很多代碼,它存在的意思就是告訴你,它要開始銷毀了,他會先把VC上的view全部釋放掉,然后再釋放掉自己,這個空函數(shù)執(zhí)行完的時候,self被釋放完了(當前這個過程是由ARC控制)