Stop NSTimer from another view?

1.6k Views Asked by At

I want to stop an NSTimer in UIRequiredPassowrdViewController from another view SettingsTabelViewController, so I first create the countdown:

class UIRequiredPassowrdViewController: UIViewController, UITextFieldDelegate {
    var timer: NSTimer?
    var remainingSeconds = 1000

    override func viewDidLoad() {
        super.viewDidLoad()

        timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "updateTimer:", userInfo: nil, repeats: true)
    }

    func updateTimer(timer: NSTimer) {
        remainingSeconds -= 1
        println(remainingSeconds)
    }

    func StopTimerNotication(){
        println("Function Start!")
        timer?.invalidate()
        timer = nil
    }
}

Then I call function StopTimerNotication() from another view SettingsTabelViewController :

@IBAction func myButtonClicked(sender: AnyObject) {
    println("Button Clicked")
    var myClass: UIRequiredPassowrdViewController=UIRequiredPassowrdViewController()
    myClass.StopTimerNotication()
}

And I run the app, the log shows correctly countdown, button clicked and run the function, but the timer just don't get stop:

999
998
997
996
995
994
993
992
991
990
989
Button Clicked
Function Start!
988
987
986
985

How can I solve this problem?

3

There are 3 best solutions below

0
On BEST ANSWER

myClass is a newly initialised view controller, it is totally different with the view controller in which you started the timer. So to solve your problem, basically you need to find a way to tell that specific view controller to stop its timer.
There are two common solutions for such case:
(1) Use notification: In your UIRequiredPassowrdViewController register to a specific notification, let's call it StopTimerNotification, when you receive such notification stop the timer. And in SettingsTabelViewController, send out StopTimerNotification in myButtonClicked.
(2) Use delegate: you need a simple protocol here, let's call it StopTimerProtocol which will probably have only on method func stopTimer(). And your UIRequiredPassowrdViewController needs to conform to this protocol and implement that method. Then add a delegate property which is a type of id<StopTimerProtocol> to SettingsTabelViewController. After that, when you present or push SettingsTabelViewController on top of UIRequiredPassowrdViewController set the delegate property. At last, in SettingsTabelViewController when myButtonClicked just call self.delegate.stopTimer()

6
On

Declare NSTimer as global in AppDelegate.

var timer: NSTimer? 

in your UIRequiredPassowrdViewController class

class UIRequiredPassowrdViewController: UIViewController, UITextFieldDelegate {

    var remainingSeconds = 1000

    override func viewDidLoad() {
        super.viewDidLoad()

        let appDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)

        appDelegate.timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "updateTimer:", userInfo: nil, repeats: true)
    }

    func updateTimer(timer: NSTimer) {
        remainingSeconds -= 1
        println(remainingSeconds)
    }
}

in SettingsTabelViewController have button in which you want to stop as below.

@IBAction func myButtonClicked(sender: AnyObject) {

  let appDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
  appDelegate.timer?.invalidate()   

}
0
On

Exactly what kirit said except code is in Objective-C for anyone in future who may stumble onto this post

//  AppDelegate.h
@property (nonatomic, retain) NSTimer *soundTimer;

//  ViewController.m
#import "AppDelegate.h"

//start timer - call it from anywhere in your ViewController
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
    appDelegate.soundTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(playButtonSound1) userInfo:nil repeats:NO];

//stop timer - call it from anywhere in your ViewController
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
    [appDelegate.soundTimer invalidate];
    appDelegate.soundTimer = nil;