程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#編程自學之開篇引見

C#編程自學之開篇引見

編輯:C#入門知識

C#編程自學之開篇引見。本站提示廣大學習愛好者:(C#編程自學之開篇引見)文章只能為提供參考,不一定能成為您想要的結果。以下是C#編程自學之開篇引見正文


創立一個准時器(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 燒毀了才停滯,我該若何讓它停滯呢?

  • NSTimer 被 Runloop 強援用了,假如要釋放就要挪用 invalidate 辦法。
  • 然則我想在 DemoViewController 的 dealloc 裡挪用 invalidate 辦法,然則 self 被 NSTimer 強援用了。
  • 所以我照樣要釋放 NSTimer 先,但是不挪用 invalidate 辦法就不克不及釋放它。
  • 但是你不進入到 dealloc 辦法裡我又不克不及挪用 invalidate 辦法。
  • 嗯…


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved