2011-02-09 100 views
2

我正在製作一個有計時器的應用程序。我將從指定時間到分鐘的秒數計爲0.發生這種情況時,我會啓動一個alertview。線程和NSTimer

我的結構是這樣的:

Mainthread方法分配一個新的線程,並對其進行初始化。 線程的入口點(方法)有一個計時器,它調用一個計算剩餘時間的方法,如果時間到了,則顯示一個alertview。

但是,這是正確的嗎?因爲現在我正在從另一個線程更新GUI,而不是主...並且這是不對的?而且我也顯示了這個線程的alertview。

我想製作另一種方法來封裝更新和顯示alertview的所有邏輯,並且在nstimer調用的方法中使用performSelectorInMainThread,但這是正確的嗎?

謝謝你的時間。

+0

你的時鐘怎麼樣?我有一個類似的問題,我需要每2秒監控一次URL。我想知道你使用了什麼解決方案。 [email protected] – leo 2011-09-15 07:43:06

回答

4

假設確定剩餘時間非常簡單,只需在主線程上運行定時器即可。計時器被連接到當前的runloop,所以它不會在任何地方阻塞,並且其回調方法不應該花費過多的時間來運行,因此可以很好地更新UI。

- (void) initializeTimerWithEndTime: (NSDate *) endTime 
{ 
    // call this on the main thread & it'll automatically 
    // install the timer on the main runloop for you 
    self.countdownTimer = [NSTimer scheduledTimerWithTimeInterval: 1.0 
                  target: self 
                 selector: @selector(timerTick:) 
                 userInfo: endTime 
                  repeats: YES]; 
#if __TARGET_OS_IPHONE__ 
    // fire while tracking touches 
    [[NSRunLoop mainRunLoop] addTimer: self.countdownTimer 
           forMode: UITrackingRunLoopMode]; 
#else 
    // fire while tracking mouse events 
    [[NSRunLoop mainRunLoop] addTimer: self.countdownTimer 
           forMode: NSEventTrackingRunLoopMode]; 
    // fire while showing application-modal panels/alerts 
    [[NSRunLoop mainRunLoop] addTimer: self.countdownTimer 
           forMode: NSModalPanelRunLoopMode]; 
#endif 
} 

- (void) cancelCountdown 
{ 
    [self.countdownTimer invalidate]; 
    self.countdownTimer = nil; 
} 

- (void) timerTick: (NSTimer *) aTimer 
{ 
    NSDate * endDate = [timer userInfo]; 
    NSDate * now = [NSDate date]; 

    // have we passed the end date? 
    if ([endDate laterDate: now] == now) 
    { 
     // show alert 
     [self cancelCountdown]; 
     return; 
    } 

    // otherwise, compute units & show those 
    NSUInteger units = NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit; 

    NSDateComponents * comps = [[NSCalendar currentCalendar] components: units 
                   fromDate: [NSDate date] 
                   toDate: endDate 
                   options: 0]; 
    [self.clockView setHours: comps.hour 
        minutes: comps.minute 
        seconds: comps.second]; 
} 
+0

但是,當用戶拿着一個細胞? – LuckyLuke 2011-02-09 20:02:41

1

不需要在輔助線程上運行定時器,只需在主線程上創建定時器即可。你不能從輔助線程更新GUI,是的,你可以使用performSelectorInMainThread,但爲什麼要麻煩?只要把整個事情放在主線程上,只要你的計時器不被稱爲「太頻繁」,性能就會好。

+0

如果我把定時器放在主線程中(每秒更新一次,因爲它是一個時鐘),並且用戶通過觸摸來阻塞runloop,例如時鐘停止。 – LuckyLuke 2011-02-09 19:44:26