0

Is there any corner case behaviors for removeObserver:name:object:? In the following block of code, my observer isn't being registered properly:

- (void)setPlayerItem:(AVPlayerItem *)playerItem {
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(playerItemDidReachEnd:)
                                                 name:nil
                                               object:playerItem];

    [playerItem addObserver:self
                 forKeyPath:kStatus
                    options:0
                    context:(__bridge void*)self];

    [playerItem addObserver:self
                 forKeyPath:kPlaybackBufferEmpty
                    options:0
                    context:(__bridge void*)self]; // For adding a buffering activity indicator

    id temp = playerItem_;
    playerItem_ = [playerItem retain];

    [[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:temp];
    [temp removeObserver:self forKeyPath:kPlaybackBufferEmpty];
    [temp removeObserver:self forKeyPath:kStatus];
    [temp release];
}

However, if I change the order around to:

- (void)setPlayerItem:(AVPlayerItem *)playerItem {    
    [playerItem addObserver:self
                 forKeyPath:kStatus
                    options:0
                    context:(__bridge void*)self];

    [playerItem addObserver:self
                 forKeyPath:kPlaybackBufferEmpty
                    options:0
                    context:(__bridge void*)self]; // For adding a buffering activity indicator

    id temp = playerItem_;
    playerItem_ = [playerItem retain];

    [[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:temp];
    [temp removeObserver:self forKeyPath:kPlaybackBufferEmpty];
    [temp removeObserver:self forKeyPath:kStatus];
    [temp release];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(playerItemDidReachEnd:)
                                                 name:nil
                                               object:playerItem];
}

All the notifications post just fine. This leads me to believe something strange is happening when I call:

    [[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:temp];

Am I missing something really obvious here? I'm on iOS 6 with no ARC.

wL_
  • 997
  • 8
  • 13
  • I don't see anything that would change behavior between iOS 5 and iOS 6. However, I see that the old version of your code, and possibly the new version, are broken if the old `playerItem` is `nil` or equal to the new `playerItem`. – rob mayoff Oct 10 '12 at 03:25

3 Answers3

1

Found the answer. Turns out it has to do with passing in nil for the observer name. Calling [[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:temp]; will remove self from observing any notifications posted by temp. However, in the corner case that temp is nil, this line of code will remove self as an observer all together.

wL_
  • 997
  • 8
  • 13
0

Name shouldn't be nil. Did you try giving your observer a name?

Lee
  • 31
  • 1
0

@Lee is correct that the name should not be nil but it also should not be the name of the observer. Rather it should be the name of the notification that you are registering to observe. e.g., UIDeviceOrientationDidChangeNotification. Add the name of the notification that you want to observe in that param and also pass it as the name param when you remove observer

geraldWilliam
  • 4,123
  • 1
  • 23
  • 35
  • That shouldn't be an issue. According to the docs, having nil for the notification name means the notification center will send the observer all notifications posted by the object being observed. Same with removing an observer. Passing nil will remove the observer from all notifications posted by observed object. – wL_ Oct 10 '12 at 04:40
  • Are you sure that the object you are removing observer from is the same object you are adding yourself as an observer of? – geraldWilliam Oct 10 '12 at 04:44
  • Thx for that clarification btw, I was unaware of that – geraldWilliam Oct 10 '12 at 04:44
  • I double checked. Doesn't seem to be the case. This method is only called once. So on the first call, temp == nil. – wL_ Oct 10 '12 at 04:51
  • So what happens I you pass playerItem as the object in removeObserver instead of temp? – geraldWilliam Oct 10 '12 at 05:19