user2681789
user2681789

Reputation: 905

NSTimer does not stop

     [self performSelectorInBackground:@selector(method) withObject:nil];

    -(void)method 
    {
    timer1 = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(getLastImageName1) userInfo:nil repeats:YES];
                runLoop = [NSRunLoop currentRunLoop];
                [runLoop addTimer:timer1 forMode:NSRunLoopCommonModes];
                [runLoop run];
    }

-(void)viewdidunload
{
  [timer1 invalidate];
  timer1=nil;
}

I start Timer in HomeViewController even I invalidate, it keeps running in OtherViewController. What is wrong with my code?

Upvotes: 2

Views: 1925

Answers (5)

Vaibhav Saran
Vaibhav Saran

Reputation: 12908

-(void)viewDidUnload is a delegate which fires on memory warning only and is deprecated after iOS 6. It will also never fire on the simulator.

Stop timer in

- (void)viewWillDisappear:(BOOL)animated

or in

- (void)viewDidDisappear:(BOOL)animated

Upvotes: -3

nhgrif
nhgrif

Reputation: 62052

First of all, when you're overriding life cycle methods, you should include a call to the super version of that method.

Second of all, Objective-C is case sensitive, so even if your app would try to call the life-cycle even, viewDidUnload, your method would simply never be called because that's what you titled your method.

Third of all, viewDidUnload was deprecated in iOS 6.0 and shouldn't be used at all by this point unless you're going way out of your way to support backward compatibility. It will never be called in iOS 6.0 and greater.


If you want the timer to stop when the user navigates away from the current view, you'll want something like this:

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];

    if (timer1.isValid) {
        [timer1 invalidate];
    }
    timer1 = nil;
}

If you're looking for something else, you'll need to elaborate on what it is you want to accomplish exactly.


If you ARE working on a pre-iOS 6.0 project, for whatever reason, the reason your method isn't being called is at least in part because it is spelled wrong. Again, Objective-C is case sensitive. Your method name should be spelled viewDidUnload.


For future reference, the question shouldn't really be "why isn't my timer invalidating?" You should have start by using breakpoints or NSLog statements to determine whether or not your method, viewdidunload, which tries to invalidate the timer even fires. When you find out it's not being called, do a search to ask "How come viewdidunload isn't called?" Then you'll go fix the capitalization problem and the problem will (probably) remain, so do some more research. And if at the end, you still can't figure it out, as a worst case scenario, the post question should be "how come viewdidunload isn't called?"

Upvotes: 12

badCodeSucks
badCodeSucks

Reputation: 41

There is no need to add the timer (again) on the main run loop. Or is it necessary for You to run it also in commonModes? For me it was never necessary.

From the NSTimer Documentation:

scheduledTimerWithTimeInterval:invocation:repeats:

Creates and returns a new NSTimer object and schedules it on the current run loop in the default mode.

Since the NSRunLoop Documentation points out that you can add timer on several run loop modes, maybe this is the problem.

addTimer:forMode:

Discussion You can add a timer to multiple input modes. While running in the designated mode, the receiver causes the timer to fire on or after its scheduled fire date. Upon firing, the timer invokes its associated handler routine, which is a selector on a designated object.

Also I don't get why you are invoking the timer creation with performSelector? I just wrote a minimalistic sample. thats totally working!

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(doWork:) userInfo:Nil repeats:YES];

}

- (void)viewDidDisappear:(BOOL)animated{

    [self.timer invalidate];

    [super viewDidDisappear:animated];

}

- (void) doWork:(id) userInfo
{

    NSLog(@"Working again");

}

Hope this helps.

Upvotes: 0

Bhavesh Nayi
Bhavesh Nayi

Reputation: 3656

    [self performSelector:@selector(method) withObject:nil afterDelay:0.0];
-(void)method
{
    timer1 = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(getLastImageName1) userInfo:nil repeats:YES];
    runLoop = [NSRunLoop currentRunLoop];
    [runLoop addTimer:timer1 forMode:NSRunLoopCommonModes];
    [runLoop run];
}

- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];

    [timer1 invalidate];
    timer1=nil;
}

Upvotes: 1

Yohan
Yohan

Reputation: 1108

timer1 = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(getLastImageName1:) userInfo:nil repeats:YES]; 

set colon for function in selector

-(void) getLastImageName1 :(NSTimer*)timer1
    {

       //Do your all process and invalidate after completion

        [timer1 invalidate];

    }

or if you want to remove timer after moving to next view controller use how @nhgrif mentioned

- (void)viewDidDisappear:(BOOL)animated
{
    [timer1 invalidate];
}

Upvotes: 1

Related Questions