暂停NSTimer

时间:2011-05-02 21:34:48

标签: iphone nstimer nsthread

我有一个UIView,其中包含UITableViewUIImageViewUITableView占据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 个答案:

答案 0 :(得分:2)

保留对您创建的计时器的引用,以便在需要时停止它。下次需要时,您可以创建一个新的计时器。这听起来像你最好的地方是在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 :(得分:1)

您可以使用NSTimer的invalidate方法来销毁计时器。

然后,当您返回视图时,您必须像在startTimerThread方法中那样重新创建它。

答案 2 :(得分:1)

要从startTimerThread方法外部访问该主题,您应该为您的类添加一个属性。我会建议ivar上的属性,因为你可以自动合成原子访问器。你用计时器做什么取决于你是想暂停还是停止它。

停止计时器意味着下次启动时,它将以剩余的3秒钟开始。这意味着如果计时器在您停止时会在1秒钟内闪光,则再次启动计时器后仍需要3秒钟才能启动。但是,停止非常简单。 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
}

答案 3 :(得分:0)

创建一个标志(BOOL)来控制图像的更新。

当您希望更新图像的例程忽略计时器事件触发调用它的事实时,清除它。如果要恢复图像更新,只需设置标志即可。也许是这样的:

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

由于你每隔三秒才开始一次方法,所以让计时器运行并不是什么大事。

你可以做的另一件事是设置计时器,使其重复。有了这个,重新启用计时器的决定可以在代码中的其他地方而不是自动进行。您甚至可以在回调函数中执行此操作,如果愿意,仍然可以使用“image_updates_enabled”标志。