創立一個准時器(NSTimer)
- (void)viewDidLoad { [super viewDidLoad]; [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(actionTimer:) userInfo:nil repeats:YES]; } - (void)actionTimer:(NSTimer *)timer { }
NSTimer默許運轉在default mode下,default mode簡直包含一切輸出源(除NSConnection) NSDefaultRunLoopMode形式。
actionTimer辦法會每隔1s中被挪用一次。NSTimer應用起來是否是異常簡略。這是NSTimer比擬低級的運用。
當主界面被滑動時NSTimer掉效了
主界面被滑動是甚麼意思呢?就是說主界面有UITableView或許UIScrollView,滑動UITableView或許UIScrollView。這個時刻NSTimer掉效了。
我們來寫一個demo,在一個有UITableView的UIViewController上啟動准時器,每1s數字加1,並將這個數字顯示在UILabel下面.
- (void)viewDidLoad { [super viewDidLoad]; [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(actionTimer:) userInfo:nil repeats:YES]; } - (void)actionTimer:(NSTimer *)timer { self.number++; self.label.text = [NSString stringWithFormat:@"%d",self.number]; NSLog(@"%d",self.number); }
關於UITableView和UILabel的創立我省去了。具體的代碼可以點擊這裡下載:IOSStrongDemo,IOSStrongDemo我會赓續更新,年夜家在github上star一下。
如許當用戶在拖動UITableView處於UITrackingRunLoopMode時,NSTimer就掉效了,不克不及fire。self.label上的數字也就沒法更新。
修正NSTimer的run loop
處理辦法就是將其參加到UITrackingRunLoopMode形式或NSRunLoopCommonModes形式中。
[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
或許
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
NSRunLoopCommonModes:是一個形式聚集,當綁定一個事宜源到這個形式聚集的時刻就相當於綁定到了聚集內的每個形式。
fire
我們先用 NSTimer 來做個簡略的計時器,每隔5秒鐘在掌握台輸入 Fire 。比擬想固然的做法是如許的:
@interface DetailViewController () @property (nonatomic, weak) NSTimer *timer; @end @implementation DetailViewController - (IBAction)fireButtonPressed:(id)sender { _timer = [NSTimer scheduledTimerWithTimeInterval:3.0f target:self selector:@selector(timerFire:) userInfo:nil repeats:YES]; [_timer fire]; } -(void)timerFire:(id)userinfo { NSLog(@"Fire"); } @end
運轉以後確切在掌握台每隔3秒鐘輸入一次 Fire ,但是當我們從這個界面跳轉到其他界面的時刻卻發明:掌握台還在源源赓續的輸入著 Fire 。看來 Timer 並沒有停滯。
invalidate
既然沒有停滯,那我們在 DemoViewController 的 dealloc 裡加上 invalidate 的辦法:
-(void)dealloc { [_timer invalidate]; NSLog(@"%@ dealloc", NSStringFromClass([self class])); }
再次運轉,照樣沒有停滯。緣由是 Timer 添加到 Runloop 的時刻,會被 Runloop 強援用:
Note in particular that run loops maintain strong references to their timers, so you don't have to maintain your own strong reference to a timer after you have added it to a run loop.
然後 Timer 又會有一個對 Target 的強援用(也就是 self ):
Target is the object to which to send the message specified by aSelector when the timer fires. The timer maintains a strong reference to target until it (the timer) is invalidated.
也就是說 NSTimer 強援用了 self ,招致 self 一向不克不及被釋放失落,所以也就走不到 self 的 dealloc 裡。
既然如斯,那我們可以再加個 invalidate 按鈕:
- (IBAction)invalidateButtonPressed:(id)sender { [_timer invalidate]; }
嗯如許便可以了。(在 SOF 上有人說該在 invalidate 以後履行 _timer = nil ,未能懂得為何,假如你曉得緣由可以告知我:)
在 invalidate 辦法的文檔裡還有這如許一段話:
You must send this message from the thread on which the timer was installed. If you send this message from another thread, the input source associated with the timer may not be removed from its run loop, which could prevent the thread from exiting properly.
NSTimer 在哪一個線程創立就要在哪一個線程停滯,不然會招致資本不克不及被准確的釋放。看起來各類坑還很多。
dealloc
那末成績來了:假如我就是想讓這個 NSTimer 一向輸入,直到 DemoViewController 燒毀了才停滯,我該若何讓它停滯呢?
【iOS中的NSTimer准時器的初步應用解析】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!