Iphone 暂停NSTimer
我有一个Iphone 暂停NSTimer,iphone,nstimer,nsthread,Iphone,Nstimer,Nsthread,我有一个UIView,其中有一个UITableView和一个UIImageView。UITableView占据了UIView的上半部分。UIImageView获取UIView的下半部分 我正在使用NSTimer更新在UIImageView中显示的图像。基本上,每隔3秒钟,UIImageView加载一个新的UIImage 问题是,如果我从UITableView中选择一行,NSTimer将保持运行。如何停止didSelectRowFromIndexPath上的NSTimer,然后在视图返回屏幕时再次
UIView
,其中有一个UITableView
和一个UIImageView
。UITableView
占据了UIView
的上半部分。UIImageView
获取UIView
的下半部分
我正在使用NSTimer
更新在UIImageView
中显示的图像。基本上,每隔3秒钟,UIImageView
加载一个新的UIImage
问题是,如果我从UITableView
中选择一行,NSTimer
将保持运行。如何停止didSelectRowFromIndexPath
上的NSTimer
,然后在视图返回屏幕时再次启动它
-(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];
}
您可以使用NSTimer的
invalidate
方法销毁计时器
- (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
}
然后,当您返回视图时,您必须重新创建它,就像您在
startTimerThread
方法中所做的那样。您可以使用NSTimer的invalidate
方法来销毁计时器
- (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
}
然后,当您返回视图时,您必须重新创建它,就像您在
startTimerThread
方法中所做的那样。要从startTimerThread
方法外部访问线程,您应该向类中添加属性。我建议使用ivar上的属性,因为您可以自动合成原子访问器。您对计时器的操作取决于您是想暂停还是停止计时器
停止计时器意味着您下次启动它时,它将在剩余的3秒钟内启动。这意味着,如果计时器在您停止时在1秒内启动,则再次启动后仍需3秒时间启动。然而,停止是非常简单的。stopTimerThread
的定义如下:
- (void)stopTimerThread {
NSTimer *theTimer = self.timer;
[theTimer invalidate];
self.timer = nil;
}
- (void)stopTimerThread {
NSTimer *theTimer = self.timer;
NSDate *fireDate = [theTimer fireDate];
[theTimer invalidate];
self.timerTimeRemaining = - [fireDate timeIntervalSinceNow];
self.timer = nil;
}
由于您的另一个线程中的runloop现在没有源,它将自动退出,线程将结束,因此当您想再次启动它时,可以使用startTimerThread
暂停计时器意味着,如果您暂停计时器时它将在1秒内启动,则在您重新启动计时器后它将在1秒内启动。为此,您还需要一个包含计时器启动前剩余时间的属性,该属性将在stopTimerThread
中设置,并在startTimerThread
中使用。stopTimerThread
的实现如下:
- (void)stopTimerThread {
NSTimer *theTimer = self.timer;
[theTimer invalidate];
self.timer = nil;
}
- (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
}
-(无效)startTimerThread{
//设置自动释放池,获取运行循环
NSTimeInterval timeLeft=self.timerTimerMining;
如果(timeLeft要从startTimerThread
方法外部访问线程,您应该向类中添加属性。我建议使用ivar上的属性,因为您可以自动合成原子访问器。如何使用计时器取决于您是否要暂停或停止它
停止计时器意味着您下次启动它时,它将在剩余的3秒钟内启动。这意味着如果您停止计时器时计时器将在1秒内启动,则在您再次启动它后仍需要3秒钟才能启动。但是,停止非常简单。stopTimerRead
将定义如下:
- (void)stopTimerThread {
NSTimer *theTimer = self.timer;
[theTimer invalidate];
self.timer = nil;
}
- (void)stopTimerThread {
NSTimer *theTimer = self.timer;
NSDate *fireDate = [theTimer fireDate];
[theTimer invalidate];
self.timerTimeRemaining = - [fireDate timeIntervalSinceNow];
self.timer = nil;
}
由于您的另一个线程中的runloop现在没有源,它将自动退出,线程将结束,因此当您想再次启动它时,可以使用startTimerThread
暂停计时器意味着,如果您暂停计时器时它将在1秒内启动,则它将在您重新启动计时器后1秒启动。为此,您还需要一个包含计时器启动前剩余时间的属性,该属性将在stopTimerThread
中设置,并在startTimerThread
中使用。stopTime的实现rThread
如下:
- (void)stopTimerThread {
NSTimer *theTimer = self.timer;
[theTimer invalidate];
self.timer = nil;
}
- (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
}
-(无效)startTimerThread{
//设置自动释放池,获取运行循环
NSTimeInterval timeLeft=self.timerTimerMining;
如果(timeLeft保留对您创建的计时器的引用,以便在需要时停止它。下次需要它时,您可以创建一个新的计时器。听起来这样做的最佳位置是在ViewDidDisplay:和ViewWillEnglish:。我不确定您为什么要在新线程上启动计时器。您可能有很好的理由这样做,但我从来没有必要这样做
//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;
}
保留对您创建的计时器的引用,以便在需要时停止它。下次需要时,您只需创建一个新计时器。听起来这样做的最佳位置是在ViewDidExample:和ViewWillEnglish:。我不确定您为什么要在新线程上启动计时器。您可能有很好的理由这样做,但我从未这样做过我们需要这样做
//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;
}
创建一个标志(BOOL)来控制图像的更新
当您希望更新映像的例程忽略计时器事件触发调用映像的事实时,请清除该选项。当您希望映像更新恢复时,只需设置标志。可能类似于以下内容:
-(void)ImageUpdater:(NSTimer *)theTimer
{
if(image_updates_enabled)
{
// Code to update image
}
}
由于您仅每三秒触发一个方法,因此让计时器运行也没什么大不了的
你可以做的另一件事是设置计时器,使其不重复。有了它,重新启用计时器的决定可以在代码中的其他地方做出,而不是自动进行。你甚至可以在回调函数中执行此操作,并且仍然使用“image\u updates\u enabled”如果愿意,请标记。创建一个标记(BOOL)来控制图像的更新
当你想把日常工作做完的时候,就把它清除掉