Problem Stopping NSTimer

Discussion in 'Mac Programming' started by stadidas, Dec 2, 2006.

  1. stadidas macrumors regular

    Joined:
    Feb 27, 2006
    Location:
    Kent, United Kingdom
    #1
    In my MyDocument class I have these two methods:

    Code:
    - (void)setupTimer:(id)sender
    {
    	timer = [NSTimer scheduledTimerWithTimeInterval:1
    											 target:self
    										   selector:@selector(updateDatePickers:)
    										   userInfo:nil
    											repeats:YES];
    }
    
    - (void)updateDatePickers:(NSTimer *)aTimer
    {
    	NSDate *temp = [NSDate date];
    	[currentDate setDateValue:temp];
    }
    
    setupTimer is called from windowControllerDidLoadNib. My problem is that when I close the window the NSTimer keeps firing the updateDatePickers method, causing the program to crash. I have tried invalidating and releasing the time in my classes dealloc method, but this doesn't work. Doers anyone know how to stop the timer from firing when the window is closed?
     
  2. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #2
    You need to retain it the first time, or use the passed timer on your action:

    Code:
    - (void)setupTimer:(id)sender
    {
    	timer = [[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(updateDatePickers:) userInfo:nil repeats:YES] retain];
    }
    
    - (void)updateDatePickers:(NSTimer *)aTimer
    {
    	NSDate *temp = [NSDate date];
    	[currentDate setDateValue:temp];
    
    	// aTimer is the same timer above, so you can also call [aTimer invalidate] here
    }
    
    - (void)stopTimer
    {
    	[timer invalidate];
    	[timer release];
    }
    
    - (void)dealloc
    {
    	[self stopTimer];
    	[super dealloc];
    }
     
  3. stadidas thread starter macrumors regular

    Joined:
    Feb 27, 2006
    Location:
    Kent, United Kingdom
    #3
    I've made those changes but the program still crashes.
    I can't use [aTimer invalidate] in updateDatePickers because I want the timer to keep firing for the life of the window. Even though I have [self stopTimer]; in the dealloc method, GDB still highlights [currentDate setDateValue:temp]; in the updateDatePickers method when the app freezes. I presume that the timer is still firing and calling this method after the window has closed and 'currentDate' is deallocated.
     
  4. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #4
    In the timer action, just check for [[self window] isVisible], and if it's visible, update the GUI. If not, ignore any GUI updates until it's visible again.
     
  5. MongoTheGeek macrumors 68040

    MongoTheGeek

    Joined:
    Sep 13, 2003
    Location:
    Its not so much where you are as when you are.
    #5
    He still has the problem that he is invoking a method of an object which has been deallocated.

    The invalidate in the dealloc should fix it. I was just checking my code and that is all I had to do to handle it.
     
  6. stadidas thread starter macrumors regular

    Joined:
    Feb 27, 2006
    Location:
    Kent, United Kingdom
    #6
    My code looks like this:
    Code:
    - (void)updateDatePickers:(NSTimer *)aTimer
    {
    	if ([[self window] isVisible]) {
    		NSDate *temp = [NSDate date];
    		[currentDate setDateValue:temp];
    	}
    }
    
    and I get this error in the Xcode terminal:
    2006-12-02 18:55:54.719 AssetMonitor[2206] *** NSTimer discarding exception '*** -[MyDocument window]: selector not recognized [self = 0x34ecb0]' that raised during firing of timer with target 34ecb0 and selector 'updateDatePickers:'
    I don't know why calling stopTimer in the dealloc method isn't working.
     
  7. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #7
    Oops, didn't see the MyDocument part. Change [self window] to [self windowForSheet]
     
  8. stadidas thread starter macrumors regular

    Joined:
    Feb 27, 2006
    Location:
    Kent, United Kingdom
    #8
    Fantastic. I was going to try that earlier but didn't for some reason. It works now though.
    The timers not being deallocated is probably causing a memory leak, although I can't imagine them using much memory, so I'm not too worried for now.
     

Share This Page