【问题标题】:Reset NSTimer after navigating to another view导航到另一个视图后重置 NSTimer
【发布时间】:2013-05-22 10:28:51
【问题描述】:

目前我正在开发一个需要秒表说 1 分钟的游戏,当用户点击播放按钮进入游戏屏幕时,我希望运行秒表倒计时 1 分钟 01:00,00:59 ,00:58 等。出于这个原因,我搜索并发现 NSTimer 将是实现秒表的理想选择。因此我拿了一个标签,创建了一个 NSTimer 实例,分配了时间间隔并开始减少计时器标签中的值,即:

-(void)viewDidAppear:(BOOL)animated
{
    self.stopWatchTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(viewWillAppear:) userInfo:nil repeats:YES];
    [super viewDidAppear:YES];
}

-(void)viewWillAppear:(BOOL)animated
{
    static int currentTime = 60;
    int newTime = currentTime--;
    int minutesRemaining = newTime / 60; // integer division, truncates fractional part
    int secondsRemaining = newTime % 60; // modulo division

    self.timerLabel.text = [NSString stringWithFormat:@"%02d:%02d", minutesRemaining, secondsRemaining];

    if ([self.timerLabel.text isEqualToString:@"00:00"])
    {
        [stopWatchTimer invalidate];
    }
    [super viewWillAppear:YES];
}

这里的问题是计时器开始运行 01:00,00:59,00:58 并继续运行,比如说在第 53 秒,我导航到另一个视图并返回,它从 00:53,00 开始运行: 52 等等,但我希望它从 01:00 开始运行,为此我在 viewDidDisappear 中实现了使 NSTimer 无效,即

-(void)viewDidDisappear:(BOOL)animated
{
    if ([stopWatchTimer isValid])
    {
        [stopWatchTimer invalidate];
        self.stopWatchTimer = nil;
    }
    [super viewDidDisappear:YES];
}

同样的问题仍然存在!

对该问题进行了大量研究,但没有发现有用且有效的答案。

有人可以指导我吗,感谢任何帮助。

提前谢谢大家:)

【问题讨论】:

    标签: iphone nstimer reset


    【解决方案1】:

    您将选择器viewWillAppear 用于计时器。 viewWillAppear 是 viewController 上的一个方法,当视图出现在屏幕上时会调用它,你不应该自己调用它。相反,创建您自己的方法来减少计时器:

    -(void)viewDidAppear:(BOOL)animated
    {
      [super viewDidAppear:animated];
      self.stopWatchTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateTime:) userInfo:nil repeats:YES];
      currentTime = 60; // This could be an instance variable
      self.timerLabel.text = @"01:00";
    }
    
    
    -(void)updateTime {
      int newTime = currentTime--;
      int minutesRemaining = newTime / 60; // integer division, truncates fractional part
      int secondsRemaining = newTime % 60; // modulo division
    
      self.timerLabel.text = [NSString stringWithFormat:@"%02d:%02d", minutesRemaining, secondsRemaining];
    
      if ([self.timerLabel.text isEqualToString:@"00:00"])
      {
          [self.stopWatchTimer invalidate];
      }
    }
    
    -(void)viewDidDisappear:(BOOL)animated
    {
     [super viewDidDisappear:animated];
      if ([self.stopWatchTimer isValid])
      {
        [self.stopWatchTimer invalidate];
        self.stopWatchTimer = nil;
      }
    }
    

    使用这种技术,计时器负责每秒调用一次,但您可能会在几秒钟后遇到计时问题。为了获得更准确的计时,您应该存储开始倒计时的时间,然后在每次updateTime 调用时,将当前时间与存储的开始时间进行比较。

    添加到您的界面:

    @property (nonatomic) NSTimeInterval startTime;
    

    然后在实现中:

    -(void)viewDidAppear:(BOOL)animated
    {
        self.startTime = [NSDate timeIntervalSinceReferenceDate];
        self.duration = 60; // How long the countdown should be
        self.stopWatchTimer = [NSTimer scheduledTimerWithTimeInterval:0.1
                                                               target:self
                                                             selector:@selector(updateTime)
                                                             userInfo:nil
                                                              repeats:YES];
        self.timerLabel.text = @"01:00"; // Make sure this represents the countdown time
    }
    
    -(void)updateTime {
    
      int newTime = self.duration - (round([NSDate timeIntervalSinceReferenceDate] - self.startTime));
      int minutesRemaining = newTime / 60; // integer division, truncates fractional part
      int secondsRemaining = newTime % 60; // modulo division
    
      self.timerLabel.text = [NSString stringWithFormat:@"%02d:%02d", minutesRemaining, secondsRemaining];
    
      if (newTime < 1)
      {
        [self.stopWatchTimer invalidate];
    
        /* Do more stuff here */
    
      }
    }
    
    -(void)viewDidDisappear:(BOOL)animated
    {
     [super viewDidDisappear:animated];
      if ([self.stopWatchTimer isValid])
      {
        [self.stopWatchTimer invalidate];
        self.stopWatchTimer = nil;
      }
    }
    

    代码中有一些额外的(不相关的)cmets:

    在实现viewDidDisappear: 时,将animated 参数传递给对super 的调用: [超级 viewDidDisappear:动画]; 在实现viewDidAppear: 时,将animated 参数传递给对super 的调用,另外,请确保在方法中首先调用super,然后再执行任何其他操作

    【讨论】:

    • Perfect Marcel,它有效,但唯一的问题是标签显示上一次说 00:51,然后更改为 01:00 并且计时器工作正常,但我不希望上一次当我回到视图时可见。谢谢:)
    • 我已经更新了示例代码。确保在视图出现后立即在标签上设置文本。
    • 它对 Marcel 有效,但对您的答案稍作修改,这将使其正常工作,我打算编辑您的答案,可以吗?
    • 对不起,如果我冒昧地向您寻求进一步的帮助,我需要在另一个问题上帮助我,我有一个包含数据的 txt 文件,例如 @"Cat@milk,Bird@种子,Man@food" 等我已经成功提取了完整的数据: NSString *gmatFileString = [NSString stringWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"gmatwords" ofType:@"txt"] encoding:NSUTF8StringEncoding error:nil] ; self.gmatWordsArray = [NSMutableArray arrayWithArray:[gmatFileString componentsSeparatedByCharactersInSet:[NSCharacterSet nonBaseCharacterSet]]];
    • 我想要 2 个不同的数组,一个数组存放猫、鸟、人,另一个存放牛奶、种子、食物,即@ 之前和@ 符号之后的单词
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多