19

How to check if NSTimer is running or not in Swift. In obj-c the code should be like this as I guess:

if (!myTimer) {
  //DO
}

I'm trying to set it in Swift like this and it's showing errors.

if !myTimer {
 // DO
}
CoreDo
  • 2,691
  • 4
  • 17
  • 18

4 Answers4

29

What I do (in both languages) is to make my timer weak. In swift it would be a weak optional.

weak var myTimer: NSTimer?

Then I create a timer with

myTimer = NSTimer.scheduledTimerWithTimeInterval(1,
          target: self,
          selector: "timerFired:",
          userInfo: nil,
          repeats: false)

And then you can use

if timer == nil

to tell if it's running.

To stop the timer you just call

myTimer?.invalidate()

In Objective-C it would be

[myTimer invalidate];

That works in Objective-C because sending messages to nil pointers is valid, and just does nothing.

If you don't want to use a weak optional, you can query a timer to see if it's running by looking at it's valid property.

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • 9
    Just because `timer` is not nil does not tell if it is running. – zaph Jul 02 '15 at 19:06
  • 3
    It does if you make it weak. Then the only owning reference is the run loop, and after it fires/when it's invalidated, it gets released and nil'ed out. It's handy. – Duncan C Jul 02 '15 at 19:11
  • No, with a weak pointer, timerWithTimeInterval:target:selector:userInfo:repeats: creates a timer which is immediately deallocated because it has zero strong references.. That is a degenerate case. Try what I describe. It works. I promise. – Duncan C Jul 02 '15 at 19:37
  • For this to work `myTimer` must be declared as a `weak` property as you show, which is a key point. – zaph Jul 02 '15 at 20:07
  • As an aside I was testing in `main` with this runloop: `[[NSRunLoop currentRunLoop] run];` and that is insufficient to demonstrate the `weak` nilling. – zaph Jul 02 '15 at 20:10
  • `isValid` can't be used to check if the timer is running or not. It tells if the timer is still capable of firing or not. If the timer is created with one of the init methods, meaning it's not added to any run loop and therefore it's not running, `isValid` returns true. – nyg Jul 14 '17 at 09:32
22

How about the below option? Can you see if this works for you

if myTimer.valid {
}
Subbu
  • 2,138
  • 14
  • 20
  • For this to work `myTimer` must be declared as a `weak` property. – zaph Jul 02 '15 at 20:06
  • 5
    @zaph, no. My approach of making it weak and checking for nil works, OR you can make it strong and then check to see if timer.valid == true. Using `myTimer.valid` does **NOT** require that `myTimer` be weak. – Duncan C Mar 29 '16 at 13:27
6
if !myTimer.valid {
    //DO
}
Race B
  • 1,193
  • 1
  • 8
  • 7
3

Swift 4 answer:

if timer.isValid{

            }

https://developer.apple.com/documentation/foundation/timer

Leonard
  • 2,978
  • 6
  • 21
  • 42