我有一个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];
}
答案 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”标志。