国产探花免费观看_亚洲丰满少妇自慰呻吟_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 方法。
  • 嗯…


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 墨玉县| 招远市| 介休市| 固原市| 宜兴市| 会同县| 阿鲁科尔沁旗| 美姑县| 潜山县| 阿图什市| 石狮市| 淮阳县| 宁蒗| 商丘市| 高邮市| 蓝山县| 温宿县| 任丘市| 封开县| 绥宁县| 舟山市| 迁安市| 遂宁市| 白玉县| 龙胜| 东城区| 望城县| 万荣县| 蕉岭县| 广安市| 盐山县| 长治市| 屏南县| 溧水县| 肃宁县| 南川市| 新河县| 将乐县| 渑池县| 张掖市| 隆化县|