15

I am creating and firing a NSTimer with:

ncTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
                                           target:self
                                         selector:@selector(handleTimer:)
                                         userInfo:nil
                                          repeats:YES];
[ncTimer fire];

AND

- (void)handleTimer:(NSTimer *)chkTimer {
    // do stuff
}

I am retaining my timer with:

@property (nonatomic, retain) NSTimer *ncTimer;

For some reason the timer is not repeating. It is firing once only and than never again.

Navnath Godse
  • 2,233
  • 2
  • 23
  • 32
Zigglzworth
  • 6,645
  • 9
  • 68
  • 107
  • *A stupid question on my part, but it's best to be sure:* I presume you're not invalidating the timer anywhere inside the handleTimer method? – John Parker Jan 23 '11 at 11:36
  • No I am not.. the only thing I have to add is that I am firing the timer in the viewDidLoad method – Zigglzworth Jan 23 '11 at 11:46

8 Answers8

39

The -fire: method manually fires it once. For a timer to be started and repeat, you have to add it to a runloop using [[NSRunLoop currentRunLoop] addTimer: forMode:]

Stunner
  • 12,025
  • 12
  • 86
  • 145
Walter
  • 803
  • 6
  • 7
  • 16
    This is correct, but it's simpler to use the `NSTimer` `scheduleTimerWith...` methods instead of manually adding to the run loop. – Benedict Cohen Apr 16 '12 at 11:03
29

Got it

Adding timer to mainRunLoop made it working

Here you go:

Objective C:

self.ncTimer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(handleTimer:) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

Swift 2

var ncTimer = NSTimer(timeInterval: 2.0, target: self, selector: Selector("handleTimer"), userInfo: nil, repeats: true)
NSRunLoop.mainRunLoop().addTimer(ncTimer, forMode: NSDefaultRunLoopMode)

Swift 3, 4, 5

var ncTimer = Timer(timeInterval: 2.0, target: self, selector: #selector(self.handleTimer), userInfo: nil, repeats: true)
RunLoop.main.add(ncTimer, forMode: RunLoop.Mode.default)
Karen Hovhannisyan
  • 1,140
  • 2
  • 21
  • 31
Vaibhav Saran
  • 12,848
  • 3
  • 65
  • 75
  • Wouldn't Objective C be `NSTimer *ncTimer` instead of `self.ncTimer`? Also, wouldn't you say `addTimer:ncTimer` instead of `addTimer:timer`? I have the power to edit this, but I wanted you to be aware of what needed to be done. – Volomike Jun 22 '16 at 05:06
  • 2
    Me too, this worked for me but `scheduleTimerWithTimeInterval` didn't – Husam Aug 30 '16 at 09:30
  • 3
    In swift 4: `RunLoop.main.add(timer, forMode: RunLoopMode.defaultRunLoopMode)` – JoKr Apr 24 '18 at 16:05
8

You can also copy your code inside this block, which inserts the creation of the Timer in the main thread.

The code will therefore remain:

dispatch_async(dispatch_get_main_queue(), ^{
  self.ncTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
                 target:self selector:@selector(handleTimer:) userInfo:nil repeats: YES];
});
Danilo Ramirez
  • 1,598
  • 1
  • 16
  • 22
8

You can't just assign to the timer that you have put as a property in your header. This should work:

self.ncTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self selector:@selector(handleTimer:) userInfo:nil repeats: YES];

Also: The fire method fires the timer, out of cycle. If the timer is non repeating it is invalidated. After the line that says fire, add this:


BOOL timerState = [ncTimer isValid];
NSLog(@"Timer Validity is: %@", timerState?@"YES":@"NO");
Aurum Aquila
  • 9,126
  • 4
  • 25
  • 24
4

I don't know why but Timer.scheduledTimer method is not working but Timer.init method worked.

self.timer = Timer.init(timeInterval: 10.0, repeats: true, block: { (timer) in
            print("\n--------------------TIMER FIRED--------------\n")
            self.checkForDownload()
        })
RunLoop.main.add(self.timer!, forMode: RunLoopMode.defaultRunLoopMode)
Harish Pathak
  • 1,567
  • 1
  • 18
  • 32
3

Assigning to ncTimer as you have will not initiate the properties retain functionality.

Assuming the declaration is within the member object you will need to do:

self.ncTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(handleTimer:) userInfo:nil repeats:YES]
pablasso
  • 2,479
  • 2
  • 26
  • 32
martinws
  • 124
  • 1
  • 4
1

You could write the same thing in Swift without running in main loops by:

ncTimer = Timer.scheduledTimer(timeInterval: 1.0, 
                               target: self, 
                               selector: #selector(self.handleTimer), 
                               userInfo: nil, 
                               repeats: true)
ncTimer.fire()
CoderSulemani
  • 123
  • 11
0

Swift timer with closure:

    let timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
         // Do whatever
    }
    timer.fire()
Display Name
  • 4,502
  • 2
  • 47
  • 63