国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > iOS > 正文

iOS中的NSTimer定時器的初步使用解析

2020-07-26 03:21:23
字體:
來源:轉載
供稿:網友

創建一個定時器(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 在哪個線程創建就要在哪個線程停止,否則會導致資源不能被正確的釋放??雌饋砀鞣N坑還不少。

dealloc

那么問題來了:如果我就是想讓這個 NSTimer 一直輸出,直到 DemoViewController 銷毀了才停止,我該如何讓它停止呢?

  • NSTimer 被 Runloop 強引用了,如果要釋放就要調用 invalidate 方法。
  • 但是我想在 DemoViewController 的 dealloc 里調用 invalidate 方法,但是 self 被 NSTimer 強引用了。
  • 所以我還是要釋放 NSTimer 先,然而不調用 invalidate 方法就不能釋放它。
  • 然而你不進入到 dealloc 方法里我又不能調用 invalidate 方法。
  • 嗯…


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 库伦旗| 平远县| 博客| 华蓥市| 屏南县| 阿克苏市| 林西县| 喀喇沁旗| 青州市| 怀柔区| 留坝县| 花莲县| 萍乡市| 北流市| 尚义县| 射阳县| 荥阳市| 宕昌县| 贵定县| 囊谦县| 湄潭县| 泽普县| 永兴县| 宁乡县| 新郑市| 明水县| 平乡县| 墨玉县| 平和县| 尉犁县| 溧阳市| 福贡县| 明水县| 怀宁县| 错那县| 鹤庆县| 星子县| 达拉特旗| 陵水| 马龙县| 米林县|