Нить и НСТимер - PullRequest
       29

Нить и НСТимер

2 голосов
/ 09 февраля 2011

Я делаю приложение с таймером.Я считаю минуты и секунды от заданного времени до 0. Когда это происходит, я запускаю представление оповещения.

Моя структура такова:

Метод Mainthread выделяет новый поток и инициализирует его.Точка входа (метод) для потока имеет таймер, который вызывает метод для расчета оставшегося времени и, если время истекло, отображает представление оповещения.

Однако правильно ли это?Потому что сейчас я обновляю GUI из другого потока, а не из основного ... и это плохо, верно?И я также отображаю представление оповещения из этой темы.

Я думал о создании другого метода, который инкапсулирует всю логику для обновления и отображения представления предупреждений, и в методе, который вызывает nstimer, использующий executeSelectorInMainThread, однако это правильно?.

Ответы [ 2 ]

4 голосов
/ 09 февраля 2011

Предполагая, что довольно просто определить, сколько времени осталось, просто запустите свой таймер в главном потоке.Таймер привязывается к текущему циклу выполнения, поэтому он нигде не блокируется, и его метод обратного вызова не должен занимать чрезмерное количество времени для запуска и поэтому может красиво обновлять пользовательский интерфейс.

- (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 голос
/ 09 февраля 2011

Нет необходимости запускать таймер на вторичном потоке, просто создайте таймер на основном потоке.Вы не должны обновлять графический интерфейс из вторичного потока, да, вы можете использовать executeSelectorInMainThread, но зачем?Просто поместите все это в основной поток, если ваш таймер не называется «слишком часто», производительность будет хорошей.

...