-
(
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。