user3300758
user3300758

Reputation: 285

Unable to stop NSTimer

I use this code for stopping NSTimer

[timer invalidate]
timer = nil;

It works fine for the first run. But, after I resume the timer with this code.

 timer = [NSTimer scheduledTimerWithTimeInterval:5.0
                                     target:self
                                   selector:@selector(checkNewUpdates)
                                    userInfo:nil
                                    repeats:YES];

NSTimer won't stop anymore with [timer invalidate]

Upvotes: 0

Views: 241

Answers (4)

Surjeet Singh
Surjeet Singh

Reputation: 11939

It look like multiple instance of timer is running simultaneously. You can do one thing, before start to run a new timer, check for previous instance of timer, and if timer instance is available, then invalidate it. After this start new instance

if(timer)
{
  [timer invalidate];
  timer = nil;
}
timer = [NSTimer scheduledTimerWithTimeInterval:5.0
                                     target:self
                                   selector:@selector(checkNewUpdates)
                                    userInfo:nil
                                    repeats:YES];

Upvotes: 3

cream-corn
cream-corn

Reputation: 1840

I know this doesnt answer your question per-se;

Can I suggest using polling mechanism instead of a timer? Ive had a world of trouble with NSTimers in the past and polling was a good alternative. Ive made a simple one below.

- (void) doPoll {
    // do logic here

    if (shoudStop) { 
       return;
    }

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, X * NSEC_PER_SEC)), 
                                                  dispatch_get_main_queue(), ^{
        [self doPoll];
    });
}

This is just a simple example, it does not stop retain cycles If you choose to try this, Yours should. Hope it helps.

Upvotes: 0

wottle
wottle

Reputation: 13619

Just invalidate the timer inside the selector that fires. That will ensure you have a pointer to the correct timer (which is probably why your invalidate call isn't working:

 timer = [NSTimer scheduledTimerWithTimeInterval:5.0
                                     target:self
                                   selector:@selector(checkNewUpdates:)
                                    userInfo:nil
                                    repeats:YES];

Note the colon after checkNewUpdates:

Then, in your checkNewUpdates: method, do something like this:

- (void)checkNewUpdates:(NSTimer*)timer
{
    // do somehting

    // Then, check if the criteria for stopping the timer has been met, and invalidate it here.
    if( self.shouldStopTimer )  // made up variable, use your own criteria.
    {
        [timer invalidate];
    }
}

Upvotes: 0

Rashad
Rashad

Reputation: 11197

In apple's official document they said:

You must send this message from the thread on which the timer was installed. If you send this message from another thread, the input source associated with the timer may not be removed from its run loop, which could prevent the thread from exiting properly.

If your timer is running on main thread, do this:

[timer performSelectorOnMainThread:@selector(invalidate) withObject:nil waitUntilDone:YES];

If it is on any other thread, lets call the thread myThread, then do this:

[timer performSelector:@selector(invalidate) onThread:myThread withObject:nil waitUntilDone:NO];

Hope this helps.. :)

Upvotes: 1

Related Questions