Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/35.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 暂停NSTimer_Iphone_Nstimer_Nsthread - Fatal编程技术网

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)来控制图像的更新

当你想把日常工作做完的时候,就把它清除掉