线程和NSTimer

时间:2011-02-09 19:21:21

标签: iphone cocoa-touch nstimer nsthread

我正在制作一个有计时器的应用程序。我计算从给定时间到0的分钟和秒数。当发生这种情况时,我会启动一个警报视图。

我的结构是:

Mainthread方法分配一个新线程并初始化它。 线程的入口点(方法)有一个计时器,它调用一个计算剩余时间的方法,如果时间到了,则显示一个警报视图。

但是,这是正确的吗?因为现在我从另一个线程更新GUI而不是主...这是不对的?我也在这个帖子中显示一个alertview。

我想过制作另一个方法来封装所有用于更新和显示alertview的逻辑,并且在nstimer调用的方法中使用performSelectorInMainThread,但是这是正确的吗?

感谢您的时间。

2 个答案:

答案 0 :(得分: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];
}

答案 1 :(得分:1)

无需在辅助线程上运行计时器,只需在主线程上创建计时器。您不能从辅助线程更新GUI,是的,您可以使用performSelectorInMainThread,但为什么要这么麻烦?只要将整个事情放在主线程上,只要你的计时器没有“经常”调用,性能就会没问题。