NSNotificationCenter keeping my view controller from being deallocated?

Discussion in 'Mac Programming' started by misee, Sep 21, 2011.

  1. misee macrumors member

    Joined:
    Jul 4, 2010
    #1
    I have a document based application which uses QTMovieView to display a movie. The view in which the movie is displayed is hooked to MovieViewController (a subclass of NSViewController). At first, I used QTMovieViews default controls, but once everything was running, I decided to implement my own controls. To update the play/pause button, I added added the some code to
    Code:
    // Following method is called when a new path for the movie was set
    - (void)handleMoviePathDidChange
    {
        if (self.movie) //movie holds an instance of QTMovie
            [[NSNotificationCenter defaultCenter] removeObserver:self name:QTMovieRateDidChangeNotification object:self.movie];
    
        // "Old" code that didn't cause any trouble before
        NSError *error = nil;
        self.movie = [QTMovie movieWithURL:self.moviePath error:&error];
        if (error)
            [self handleError:error];
        
        [self.movieView setMovie:self.movie];
        // End of "old" code.
        
        if (self.movie)
            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(movieRateChanged:) name:QTMovieRateDidChangeNotification object:self.movie];
    }
    
    Now, when I close the window, the MovieViewControllers dealloc is never called and the movie keeps playing (at least the sound - since the window is closed, I can't see it anymore). If I comment out the
    Code:
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(movieRateChanged:) name:QTMovieRateDidChangeNotification object:self.movie];
    and
    Code:
    [[NSNotificationCenter defaultCenter] removeObserver:self name:QTMovieRateDidChangeNotification object:self.movie];
    calls, everything works as expected again, and dealloc is called.
    I have tried registering for NSWindowWillCloseNotification and removing myself from there using
    Code:
    [[NSNotificationCenter defaultCenter] removeObserver:self]
    but that didn't help either.
    All other view controllers and the window controller are being deallocated as expected.
    Any ideas on where the problem is?
     
  2. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #2
    You registered for NSWindowWillCloseNotification on an NSWindow object right? Because I can't see why that wouldn't have worked.

    An alternative approach would be to make this class a delegate of the window and unregister in windowWillClose:(NSNotification*).
     
  3. misee thread starter macrumors member

    Joined:
    Jul 4, 2010
    #3
    Yes, I registered on a window object like so:
    Code:
    - (void)awakeFromNib
    {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowWillClose:) name:NSWindowWillCloseNotification object:[self.view window]];
    }
    
    - (void)windowWillClose:(NSNotification *)notification
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
    
    windowWillClose: is being called when I close the window, I already checked that. It seems weird, since I can't see why my calls to the notification center should increase my retain count/prevent the instance from getting deallocated.
     
  4. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #4
    Use NSLog to check whether the object that you add as an observer and the object that you remove as an observer are the same. I suspect one is some kind of controller and the other is some kind of window.
     
  5. misee thread starter macrumors member

    Joined:
    Jul 4, 2010
    #5
    It's the same:
    Code:
    -[MovieViewController handleMoviePathDidChange] Add observer <MovieViewController: 0x100ddde60> for object <QTMovie: 0x7fcdd9bb2800 time scale = 600, duration = 3550544, rate = 0.000000, tracks = { 0x7fcdd9a7efd0 0x7fcdd9a7f060 }>
    -[MovieViewController windowWillClose:] Remove observer <MovieViewController: 0x100ddde60>
    Well, I did register self, so I guess it would have been unlikely that those two are different (I did hope it was that though:p).
    Also, MovieViewController is instantiated in the document window nib file and is referenced nowhere else. I just searched my project for any occurrences of MovieViewController, but the only hits were in MovieViewController.[hm]. Target OS is 10.7 and I'm running it on 10.7.1.
     
  6. misee, Sep 22, 2011
    Last edited: Sep 22, 2011

    misee thread starter macrumors member

    Joined:
    Jul 4, 2010
    #6
    Problem solved.
    To update the position, I used a timer. This is the way I did it:
    Code:
    - (void)movieRateChanged:(NSNotification *)notification
    {
        // some code to update playing state
    
        if (self.updateTimer)
            [self.updateTimer invalidate];
        self.updateTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(updateTimerFired:) userInfo:nil repeats:YES];
    }
    
    I just went over the entire code again and saw it. I changed it to the following:
    Code:
    [self.updateTimer invalidate];
    if (self.playing)
        self.updateTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(updateTimerFired:) userInfo:nil repeats:YES];
    else
        self.updateTimer = nil;
    
    Guess I suffered some kind of delusion when I wrote that code. Just goes to show: The problem is never where you actually look for it. Thanks for your time gnasher729 and jiminaus.
     

Share This Page