將NSTimer新增至RunLoop中的兩種方法區別
-
(
BOOL
)application:(UIApplication
*)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window
= [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
//用NSObject的方法建立一個多執行緒
[self
performSelectorInBackground:@selector(multiThread) withObject:nil];
self.window.backgroundColor
= [UIColor whiteColor];
[self.window
makeKeyAndVisible];
return
YES;
}
-
(
void
)multiThread
{
NSAutoreleasePool
*pool = [[NSAutoreleasePool alloc] init];
if
(![NSThread isMainThread]) {
//
第1種方式
//此種方式建立的timer已經新增至runloop中
//
[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
//保持執行緒為活動狀態,才能保證定時器執行
//
[[NSRunLoop currentRunLoop] run];//已經將nstimer新增到NSRunloop中了
//第2種方式
//此種方式建立的timer沒有新增至runloop中
NSTimer
*timer = [NSTimer timerWithTimeInterval:1.0f target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
//將定時器新增到runloop中
[[NSRunLoop
currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
[[NSRunLoop
currentRunLoop] run];
NSLog(@
"多執行緒結束"
);
}
[pool
release];
}
-
(
void
)timerAction
{
//定時器也是在子執行緒中執行的
if
(![NSThread isMainThread]) {
NSLog(@
"定時器"
);
}
}
理解run loop後,才能徹底理解NSTimer的實現原理,也就是說NSTimer實際上依賴run loop實現的。
先看看NSTimer的兩個常用方法:
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo; //生成timer但不執行
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo; //生成timer並且納入當前執行緒的run loop來執行
NSRunLoop與timer有關方法為:
- (void)addTimer:(NSTimer *)timer forMode:(NSString *)mode; //在run loop上註冊timer
主執行緒已經有run loop,所以NSTimer一般在主執行緒上執行都不必再呼叫addTimer:。但在非主執行緒上執行必須配置run loop,該執行緒的main方法示例程式碼如下:
- (void)main
{
NSTimer *myTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timer:) userInfo:nil repeats:YES];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:myTimer forMode:NSDefaultRunLoopMode]; //實際上這步是不需要,scheduledTimerWithTimeInterval已經納入當前執行緒執行。如果使用timerWithTimeInterval則需要
while (condition)
[runLoop run];
}
實際上這個執行緒無法退出,因為有timer事件需要處理,[runLoop run]會一直無法返回。解決辦法就是設定一個截止時間:
[runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10.0]]; //每隔10秒檢查下執行緒迴圈條件,當然時間值可以根據實際情況來定。
我們通常在主執行緒中使用NSTimer,有個實際遇到的問題需要注意。當滑動介面時,系統為了更好地處理UI事件和滾動顯示,主執行緒runloop會暫時停止處理一些其它事件,這時主執行緒中執行的NSTimer就會被暫停。解決辦法就是改變NSTimer執行的mode(mode可以看成事件型別),不使用預設的NSDefaultRunLoopMode,而是改用NSRunLoopCommonModes,這樣主執行緒就會繼續處理NSTimer事件了。具體程式碼如下:
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timer:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
大家可以參看博文http://bluevt.org/?p=209,加深理解NSTimer和NSRunLoop的關係。
以前博文中提到延遲呼叫的方法,其實就是在當前執行緒的run loop上註冊timer來實現定時執行的。所以如果是在非主執行緒上使用,一定要有一個run loop。
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray*)modes;
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay;
相關文章
- C++中建立物件的兩種方法及其區別C++物件
- 建立連結串列兩種方法的區別
- GET和POST兩種基本請求方法的區別
- Javascript中兩種方式定義函式的區別JavaScript函式
- 兩種增量備份的區別!
- Java中將Excel轉換為JSON的兩種方法JavaExcelJSON
- 求陣列長度的兩種方法,以及區別(strlen sizeof)陣列
- hash和history兩種模式的區別模式
- rails中兩種回滾-reversible和revert區別AI
- 更改Linux時區的兩種方法Linux
- hibernate中建立session的兩種方式方式,區別在哪裡?Session
- vue-router的兩種模式的區別Vue模式
- 動態代理的兩種方式以及區別
- Mysql兩種主要資料引擎的區別MySql
- javascript兩種宣告函式方式的區別JavaScript函式
- GitOps中推送與拉取兩種風格的區別 – thenewstackGit
- NSTimer詳解----使用、保留環問題、與runloop的關係OOP
- tp5 db函式的兩種區別函式
- 定義函式的兩種形式及區別函式
- Golang兩種執行流程以及區別Golang
- asp.net 中兩種不同方式檔案流下載的區別?ASP.NET
- python中合併表格的兩種方法Python
- Python中各種括號的區別、用途及使用方法Python
- PHP中將ip地址轉成十進位制數的兩種實用方法PHP
- Runloop & 方法呼叫OOP
- VUE的兩種跳轉push和replace對比區別Vue
- 請教兩種Singleton Pattern 實現方式的區別!
- laravel中delete()方法和destroy()方法的區別Laraveldelete
- ScheduledExecutorService中scheduleAtFixedRate方法與scheduleWithFixedDelay方法的區別
- Java中 equals() 方法和 == 的區別Java
- Spark SQL中列轉行(UNPIVOT)的兩種方法SparkSQL
- Struts2中使用Session的兩種方法Session
- Python中的__init__()方法整理中(兩種解釋)Python
- Treeset的兩種排序方法排序
- 探討兩種迴圈表示方法的區別,while迴圈與for迴圈的小總結While
- 【教程】將Java條形碼新增到PDF文件的兩種方法Java
- Java中將XML轉換為PDF的兩種辦法JavaXML
- MySQL兩種識別是否有中文字元的方法MySql字元