2011-02-09 47 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