問題
應用需要調度代碼以在特定的時間執行。此外,你還想要重復執行任務。
解決方案
使用NSTimer調度代碼以在特定的時間執行。為了使用NSTimer,你需要有日期對象與指向應用的運行循環的引用。
注意:
NSTimer需要有運行循環,如果想在Mac或iOS應用中使用定時器,就必須有運行循環。本攻略需要應用帶有運行循環。1.11與1.12節分別介紹了創建Mac與iOS應用的步驟。
說明
本攻略的代碼位於應用委托中。通常情況下,定時器會放在自定義類或是應用控制器中。
定時器會從特定的日期與時間開始向對象發送消息。如果應用需要重復,那麼定時器可能會間隔一段時間後再發送消息。你首先需要有日期對象,用來表示定時器開始向對象發送消息的日期與時間:
NSDate *scheduledTime = [NSDate dateWithTimeIntervalSinceNow:10.0];
上述調度時間位於上面這一行代碼執行後的10秒鐘。可以在這裡使用任何日期。
接下來,通過initWithFireDate:interval:target:selector:userInfo:repeats:構造函數創建定時器:
SString *customUserObject = @"To demo userInfo";
NSTimer *timer = [[NSTimer alloc] initWithFireDate:scheduledTime
interval:2
target:self
selector:@selector(task)
userInfo:customUserObject
repeats:YES];
這裡有些內容需要說明一下。第1個參數是日期對象,指定了定時器何時變成活動狀態。接下來是間隔時間,是定時器再次發送消息前所需等待的秒數。之後是目標參數描述符,目標是方法所處的對象。selector參數是位於圓括號中的方法名,前面是@selector關鍵字。由於方法與定時器一樣都位於應用委托中,因此可以使用self關鍵字。
userInfo是定時器使用的自定義內容。可以使用任何對象,並且可以獲得正在執行的消息中的對象引用(上面的selector參數)。這裡使用了字符串,但通常會使用字典或其他集合以支持更加復雜的活動。
repeats參數表示定時器是發送一次消息,還是根據第2個參數指定的時間間隔重復發送。
接下來需要指向運行循環的引用。可以通過NSRunLoop的currentRunLoop函數獲得該引用:
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
現在,只需要將定時器添加到運行循環中即可:
[runLoop addTimer:timer forMode:NSDefaultRunLoopMode];
10秒鐘後,定時器將會開始每隔兩秒鐘向應用發送task消息。
啟動之後,如果想停止定時器,可以向定時器發送invalidate消息。這會從運行循環中刪除定時器,代碼如下所示:
[timer invalidate];
參見程序清單5-7。
代碼
程序清單5-7 main.m
#import "AppDelegate.h"
@implementation AppDelegate
@synthesize window = _window;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification{
NSDate *scheduledTime = [NSDate dateWithTimeIntervalSinceNow:10.0];
NSString *customUserObject = @"To demo userInfo";
NSTimer *timer = [[NSTimer alloc] initWithFireDate:scheduledTime
interval:2
target:self
selector:@selector(task)
userInfo:customUserObject
repeats:YES];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:timer forMode:NSDefaultRunLoopMode];
}
-(void)task:(id)sender{
NSTimer *localTimer = (NSTimer *)sender;
NSLog(@"Schedule task has executed with this user info: %@", [localTimer userInfo]);
}
@end
使用
要想使用上述代碼,請從Xcode構建並運行Mac應用。注意控制台窗口以及消息何時開始打印到日志中。此處打印出了時間戳,這樣就可以看到時間間隔的運作方式了:
2012-01-19 15:23:28.651 Timer[31067:707] Schedule task has executed with this user info: To demo userInfo
2012-01-19 15:23:30.651 Timer[31067:707] Schedule task has executed with this user info: To demo userInfo
2012-01-19 15:23:32.651 Timer[31067:707] Schedule task has executed with this user info: To demo userInfo