Приостановка NSTimer - PullRequest
       28

Приостановка NSTimer

1 голос
/ 03 мая 2011

У меня есть UIView с UITableView и UIImageView в нем.UITableView занимает верхнюю половину UIView.UIImageView занимает нижнюю половину UIView.

. Я использую NSTimer для обновления изображения, отображаемого в UIImageView.Обычно каждые 3 секунды UIImageView загружается в новый UIImage.

Проблема в том, что если я выбираю строку из UITableView, NSTimer продолжает работать.Как я могу остановить NSTimer на didSelectRowFromIndexPath, а затем запустить его снова, когда представление вернется на экран?

-(void)viewDidLoad {
NSThread* timerThread = [[NSThread alloc] initWithTarget:self selector:@selector(startTimerThread) object:nil]; //Create a new thread
    [timerThread start]; //start the thread

} // end viewDidLoad

//
-(void) startTimerThread {
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
    [[NSTimer scheduledTimerWithTimeInterval: 3.0
                                      target: self
                                    selector: @selector(loadNextPhoto)
                                    userInfo: nil
                                     repeats: YES] retain];

    [runLoop run];
    [pool release];
}

Ответы [ 4 ]

2 голосов
/ 03 мая 2011

Сохраните ссылку на таймер, который вы создаете, чтобы вы могли остановить его при необходимости.В следующий раз, когда вам это нужно, вы можете просто создать новый таймер.Похоже, что лучшие места для вас это viewDidAppear: и viewWillDisappear :.Я не уверен, почему вы запускаете таймер в новом потоке.У вас могут быть веские причины для этого, но мне никогда не нужно было этого делать.

//This code assumes you have created a retained property for loadNextPhotoTimer

    - (void)viewDidAppear:(BOOL)animated {
        [super viewDidAppear:animated];
        [self startTimer];
    }

    - (void)viewWillDisappear:(BOOL)animated {
        [super viewWillDisappear:animated];
        [self stopTimer];
    }

    - (void)startTimer {
        NSTimer *timer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:3.0] interval:3.0 target:self selector:@selector(loadNextPhoto) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
        self.loadNextPhotoTimer = timer;
        [timer release];
    }

    - (void)stopTimer {
        [self.loadNextPhotoTimer invalidate];
        self.loadNextPhotoTimer = nil;
    }
1 голос
/ 03 мая 2011

Чтобы получить доступ к потоку извне метода startTimerThread, вы должны добавить свойство в свой класс. Я бы предложил свойство over ivar, потому что вы можете автоматически синтезировать атомарные аксессоры. То, что вы делаете с таймером, зависит от того, хотите ли вы приостановить или остановить его.

Остановка таймера означает, что при следующем запуске он запустится с оставшимися 3 секундами. Это означает, что если таймер сработает через 1 секунду, когда вы его остановите, то после запуска снова все равно будет 3 секунды. Однако остановиться очень просто. A stopTimerThread будет определяться следующим образом:

- (void)stopTimerThread {
    NSTimer *theTimer = self.timer;
    [theTimer invalidate];
    self.timer = nil;
}

Поскольку у runloop в другом потоке нет источников, он автоматически завершится и поток закончится, поэтому вы можете использовать startTimerThread, когда захотите запустить его снова.

Приостановка таймера означает, что, если он сработает через 1 секунду, когда вы его приостановите, он сработает через 1 секунду после перезапуска. Для этого вам также понадобится свойство, содержащее время, оставшееся до срабатывания таймера, которое будет установлено в stopTimerThread и использовано в startTimerThread. Реализация stopTimerThread выглядит следующим образом:

- (void)stopTimerThread {
    NSTimer *theTimer = self.timer;
    NSDate *fireDate = [theTimer fireDate];
    [theTimer invalidate];
    self.timerTimeRemaining = - [fireDate timeIntervalSinceNow];
    self.timer = nil;
}

Обратите внимание, что оставшееся время установлено как отрицательное значение временного интервала, поскольку дата срабатывания будет раньше. Вам также придется изменить startTimerThread, чтобы учесть оставшееся время при настройке таймера.

- (void)startTimerThread {
    // set up autorelease pool, get run loop
    NSTimeInterval timeLeft = self.timerTimeRemaining;
    if(timeLeft <= 0.0) timeLeft = 3.0;
    NSDate *fireDate = [NSDate dateWithTimeIntervalSinceNow:timeLeft];
    NSTimer *theTimer = [[NSTimer alloc] initWithFireDate:fireDate interval:3.0 target:self selector:@selector(loadNextPhoto) userInfo:nil repeats:YES];
    [runLoop addTimer:theTimer forMode:NSDefaultRunLoopMode];
    self.timer = theTimer;
    [theTimer release];
    [runLoop run];
    // clean up
}
1 голос
/ 03 мая 2011

Вы можете использовать метод NSTimer invalidate для уничтожения таймера.

Затем вам нужно будет воссоздать его, как вы делали это в методе startTimerThread, когда вернетесь к представлению.

0 голосов
/ 03 мая 2011

Создайте флаг (BOOL) для управления обновлением изображения.

Снимите его, если хотите, чтобы подпрограмма, которая обновляет изображение, игнорировала тот факт, что он был вызван срабатыванием события таймера.Если вы хотите, чтобы обновления изображений возобновились, просто установите флажок.Может быть, что-то вроде этого:

-(void)ImageUpdater:(NSTimer *)theTimer
{
  if(image_updates_enabled)
  {
     // Code to update image
  }
}

Поскольку вы запускаете метод только каждые три секунды, запускать таймер не составляет большого труда.

Другая вещь, которую вы можетеустановить таймер так, чтобы он не повторялся .После этого решение о включении таймера может быть принято где-то еще в вашем коде, а не автоматически.Вы даже можете сделать это в функции обратного вызова и по-прежнему использовать флаг «image_updates_enabled», если хотите.

...