使用NSTimer時遇到的問題歸類

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控制)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容