如何停止NSTimer

32

嘿,我正在制作一个示例应用程序,遇到了一点困难。 我有一个表视图,然后有几行,当用户点击一行时,它会带他们到一个新的视图。 在这个视图上,我有一个播放音乐的按钮。 我使用计时器来根据音乐持续时间和剩余时间增加滑块条。

现在我的问题是,当我通过左上角的按钮返回表视图时,我应该放什么以使NSTimer停止?

这是我目前所拥有的,但我无法让重复: YES 的计时器停止。

#import "SecondViewController.h"

@implementation SecondViewController
@synthesize lbl1;
@synthesize timer;

-(IBAction) slide {
 myMusic.currentTime = slider.value;
}

-(IBAction)play
{
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateTime) userInfo:nil repeats:YES];
 slider.maximumValue = [myMusic duration];
 myMusic.volume = 0.2;
 [myMusic prepareToPlay];
 [myMusic play];
}

-(IBAction)pause
{
 [myMusic pause];
}

-(IBAction)stop
{
 slider.value = 0;
 myMusic.currentTime = 0;
 [myMusic stop];
}

- (void)updateTime{
  slider.value = myMusic.currentTime;
}

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {

  //This plays music, we must give it a path to find the file and then u can change it. 
 NSString * pathToMusicFile = [[NSBundle mainBundle] pathForResource:@"Katy" ofType:@"mp3"];
     myMusic = [[ AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:pathToMusicFile] error:NULL];
     myMusic.delegate = self;
     myMusic.numberOfLoops = -1;

 slider.value = 0;
 //[myMusic play];

    [super viewDidLoad];
}


- (void)viewDidUnload {

 [timer invalidate];
 timer = nil;
 //myMusic.currentTime = 0;
 [myMusic stop];
 [super viewDidUnload];

 // Release any retained subviews of the main view.
 // e.g. self.myOutlet = nil;
}

-(IBAction) TxtChange;{

 lbl1.text = @" test2! I CHNAGED TEXT FROM ANOTHER XIB";
}

- (void)dealloc {
 [timer invalidate];
 timer = nil; 
 [myMusic release];
    [super dealloc];
}

@end
7个回答

68

使用以下代码。它会起作用 但请记住,只有在我们的定时器处于运行模式时才能调用它,否则应用程序将崩溃。

- (void)viewWillDisappear:(BOOL)animated {
    //BEFORE DOING SO CHECK THAT TIMER MUST NOT BE ALREADY INVALIDATED
    //Always nil your timer after invalidating so that 
    //it does not cause crash due to duplicate invalidate
       if(timer)
       {
         [timer invalidate];
         timer = nil;
       }
    [super viewWillDisappear:animated];
}

我打算明天早上试一下,现在是凌晨2点,我一整天都卡在这个问题上了。希望你的解决方案有效。几个小时后我会回到这篇文章。 - cruisx
22
有人应该告诉他,他在回复你这件事上已经晚了大约三年时间......不管怎样,我的问题解决了! - Jon Mattingly
@cruisx,你的问题解决了吗? - Nurdin
在viewWillDisappear中停止计时器时要非常小心。如果您的应用程序进入后台,则不会被调用。在这种情况下,您可能希望停止计时器以避免操作系统终止您的应用程序。 - lostintranslation

13

像这样:

[yourtimername invalidate];

但是要小心,如果计时器已经停止,你就不能再停止它,否则你的应用程序会崩溃。


2
当我使一个未实例化的计时器无效时,该应用程序不会崩溃。 - IgniteCoders

8

如iCoder所说,必须在viewWillDisappear中使其无效。

我添加了以下内容,只是为了确保它能正常工作。希望它能有所帮助(并且补充iCoder的答案,不打算抄袭)。

- (void) startTimer
{
[self stopTimer];
timer = [NSTimer scheduledTimerWithTimeInterval: 5.0
                                                     target: self
                                                   selector:@selector(onTick)
                                                   userInfo: nil repeats:YES];

}

- (void) stopTimer
{
    if (timer) {
        [timer invalidate];
        timer = nil;
    }

}

7

虽然这篇文章已经发表了4年,但我希望我的翻译能够帮助下一个需要的人节省时间,避免尝试无效化NSTimer。苹果的文档中有解释,并且对我也有效。

在.h文件中:

@property(nonatomic, retain) NSTimer *yourTimer;
@property(weak) NSTimer *repeatingTimer;

in .m

@synthesize yourTimer, repeatingTimer;

在viewDidLoad方法中

yourTimer = [NSTimer scheduledTimerWithTimeInterval:(NSTimerInterval)(40.0/60.0)
                                             target:self
                                           selector:@selector(blink)
                                           userInfo:nil
                                            repeats:TRUE];

  self.repeatingTimer = yourTimer;

在我的viewDidDisappear方法中

   [repeatingTimer invalidate];
   repeatingTimer = nil;

关键在于将第一个NSTimer分配给(弱)NSTimer对象并杀死该对象。


2

你可以使用两种不同的东西

    [timername invalidate];

或者您可以使用
    timername = nil;

后者实际上不会停止计时器,而前者已经在2010年8月发布过了。 - Matthias Bauch

1

技巧是使用单例类, 谷歌myGlobals类,它通常用作单例 虽然如果您希望使用NSTimer,那么

假设视图1是您进入的视图,视图2是您返回的视图。

因此,在视图2的情况下,在viewDidLoad中编写NSTimer以使计时器失效(假设您为两个视图拥有两个单独的类)。问题将会发生,因为当您转到视图1时,视图2计时器将被释放。因此,请创建一个Singleton类并像这样保存NSTimer指针

//to be done in viewDidLoad function
theGlobals *globals = [theGlobals alloc] init];// for the singleton class to initiate,
[globals.myTimer invalidate];


//to be done in viewDidUnload
theGlobals *globals = [theGlobals alloc] init];// for the singleton class to initiate,
globals.myTimer = [NSTimer scheduledTimerWithTimeInterval: 5.0
                                                 target: self
                                               selector:@selector(onTick)
                                               userInfo: nil repeats:YES];

哦,这里是你需要的myGlobals类代码

//theglobals.h file

#import <Foundation/Foundation.h>


@interface theGlobals : NSObject 
{
    NSTimer *myTimer;
}

@property (nonatomic, copy) NSString *changeyes;



+(theGlobals*)sharedInstance;
@end

//implementaton .m file

#import "theGlobals.h"
@implementation theGlobals

@synthesize myTimer;



static theGlobals *sharedInstance;

- (id) init
{
return self;
}

+(theGlobals*)sharedInstance
{
if (!sharedInstance)
{
    sharedInstance = [[theGlobals alloc] init];
}
return sharedInstance;
}
@end

0

只需使计时器失效

[timer invalidate];


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接