NSTimer 不会随着导航控制器停止

NSTimer Does not Stop with Navigation Controller

我是 iOS 的新人, 在我的项目中,我将 NSTimer 与导航控制器一起使用。 我在我的项目中使用了两个 Classes, Class 1 是 ViewController,第二个 Class 是 PlayTheme。 ViewController 和 PlayTheme Classes 与 segue 相连。 在 PlayTheme Class 中,我使用了 NSTimer 并且 "FiredTimer method" 每 10 毫秒调用一次。 PlayTheme Class 的源代码是: 下面的 NSTimer Start 方法

- (IBAction)startTimerMethod:(id)sender
{
    UIBackgroundTaskIdentifier bgTask =0;
        UIApplication  *app = [UIApplication sharedApplication];
        bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
            [app endBackgroundTask:bgTask];
        }];

    timer = [NSTimer
             scheduledTimerWithTimeInterval:0.01
             target:self
             selector:@selector(timerFired:)
             userInfo:nil
             repeats:YES];
}

下面的方法是停止定时器

- (IBAction)stopTimerMethod:(id)sender
{
    if([timer isValid])
    {
        [timer invalidate];
        timer=Nil;
    }
}

两种方法都有效,但是当我按照以下步骤操作时,计时器不会停止:

  1. 我在 PlayTheme Class 和 StartTime
  2. 返回 ViewController
  3. 回来玩主题Class
  4. 和StopTimer方法调用,方法调用但不停止定时器

给我解决问题的建议,并告诉我 NSTimer 如何在后台工作以使用 NSTimer 在特定时间播放声音?

感谢您的进阶。

当您退出 PlayTheme 视图控制器时,您将失去对计时器的引用。如果您想保留对计时器的引用,则需要将计时器存储在某个地方 'globally'。执行此操作的方式和位置取决于应用程序的结构。

编辑

澄清一下:我不建议使用全局变量!我只是写那个来指示一个变量 'exists' 在更多地方然后只是一个控制器。查看@sweepy_ 的回答以获得可能的解决方案。

请问您是如何添加定时器的?

应该是这样的-

[[NSRunLoop mainRunLoop] addTimer: 计时器 forMode:NSRunLoopCommonModes];

有几种解决方案可以解决您的问题:

  • 不鼓励 - 全局存储对 NSTimer 实例的引用(查看 Singleton 设计模式)
  • 推荐 - 从第一个视图控制器实例化您的计时器,以便您始终对其保留引用,并最终将其传递给目标 PlayTheme 视图控制器。

永远记住,如果您必须与多个实例共享一个元素,则该元素必须由所有这些实例的第一个共同父亲管理。

 VC1 -> VC2 -> VC3
 VC1 -> VC5
 // In such a case, if both VC3 and VC5 need to share an element,
 // this one must be managed by VC1

创建一个后台计时器子类 NSOperation 并创建它的实例。此外,为了让计时器在特定持续时间内保持活动状态,您需要从当前时间 + 持续时间指定日期,就像这样 -

#import <Foundation/Foundation.h>

@interface BackgroundTimer : NSOperation
{
    BOOL _done;
}
@end



#import "BackgroundTimer.h"

@implementation BackgroundTimer

-(void) main
{
    if ([self isCancelled])
    {
        return;
    }

    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:30
                                             target:self
                                           selector:@selector(timerFired)
                                           userInfo:nil
                                            repeats:YES];

    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

    //keep the runloop going as long as needed
    while (!_done && [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
                                              beforeDate:[NSDate dateTillTheSpecificTime]]);

}

@end