线程和 NSTimer

发布于 2024-10-16 09:34:21 字数 338 浏览 7 评论 0原文

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

我的结构是这样的:

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

然而,这是正确的吗?因为现在我正在从主线程之外的另一个线程更新 GUI...这很糟糕,对吧?我还显示了该线程的警报视图。

我想制作另一种方法来封装用于更新和显示警报视图的所有逻辑,并在 nstimer 调用的方法中使用performSelectorInMainThread,但这是否正确?

感谢您抽出时间。

I am making an application that has a timer. I count the minutes and seconds from a given time down to 0. When this happen I launch an alertview.

My structure is this:

Mainthread method allocate a new thread and initialize it.
The entrypoint(method) for the thread has a timer which invokes a method for calculating time left, and if the time is up, displays an alertview.

However, is this correct? Because now I am updating GUI from another thread than the main...and that is bad right? And I am also displaying an alertview from this thread.

I thought of making another method that encapsulate all the logic for updating and displaying the alertview and in the method that the nstimer invokes use the performSelectorInMainThread, however is this correct?

Thanks for your time.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

緦唸λ蓇 2024-10-23 09:34:21

假设确定剩余时间相当简单,只需在主线程上运行计时器即可。计时器附加到当前的运行循环,因此它不会在任何地方阻塞,并且其回调方法不应花费过多的时间来运行,因此可以很好地更新 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];
}

Assuming that it's fairly simple to determine how much time is left, just run your timer on the main thread. The timer gets attached to the current runloop, so it's not blocking anywhere, and its callback method shouldn't take an inordinate amount of time to run, and can therefore update the UI nicely.

- (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];
}
沫尐诺 2024-10-23 09:34:21

无需在辅助线程上运行计时器,只需在主线程上创建计时器即可。你不能从辅助线程更新GUI,是的,你可以使用performSelectorInMainThread,但为什么要麻烦呢?只要将整个事情放在主线程上,只要你的计时器不被“太频繁”调用,性能就会很好。

No need to run the timer on a secondary thread, just create the timer on the main thread. You must not update the GUI from a secondary thread, yes you could use performSelectorInMainThread but why bother? Just put the whole thing on the main thread, as long as your timer isn't called "too often," performance will be fine.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文