removeObserver:forKeyPath:在 keyPath 通知期间崩溃

removeObserver:forKeyPath: crashes during keyPath notification

我创建了一个观察器来跟踪我的 AVPlayer 的 "rate"。每次 AVPlayer 速率按预期变化时都会显示观察者通知。但是,当我尝试在 AVPlayer 正在播放的项目播放结束时删除观察者时,我遇到以下崩溃:

*** Terminating app due to uncaught exception 'NSRangeException', reason: 'Cannot remove an observer <MediaController 0x10181e000> for the key path "rate" from <NSNotificationCenter 0x1740da080> because it is not registered as an observer.'

这没有意义,因为必须注册观察者才能删除观察者。换句话说,我删除观察者的点是在接收观察者通知的处理程序中。很明显,观察者已注册。这是我创建观察者的相关代码:

 AVPlayerItem *item = [[AVPlayerItem alloc]initWithURL:address];
 moviePlayer = [[AVPlayer alloc]initWithPlayerItem:item];

 [moviePlayer addObserver:self
               forKeyPath:@"rate"
                  options:NSKeyValueObservingOptionNew
                  context:NULL];

然后当正在播放的项目结束时,在收到观察者通知后执行以下处理程序代码:

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {

if ([keyPath isEqualToString:@"rate"]) {
    float rate = [change[NSKeyValueChangeNewKey] floatValue];
    if (rate == 0.0) {
        // Playback stopped

        if (CMTimeGetSeconds(moviePlayer.currentTime) >=
            CMTimeGetSeconds(moviePlayer.currentItem.duration)) {
            // Playback reached end

            // Remove further notifications until the next time we need the movie player
            [[NSNotificationCenter defaultCenter] removeObserver:self forKeyPath:@"rate"];

执行removeObserver 后,应用崩溃。我还尝试添加 &moviePlayer 的非空上下文并删除具有该上下文的观察者,但它仍然崩溃。我也试过延迟删除,但这也没有解决问题。

我缺少什么来避免这次崩溃?

您没有使用 NSNotificationCenter 注册观察者,而是使用 moviePlayer 对象。

尝试做:

// Remove further notifications until the next time we need the movie player
[moviePlayer removeObserver:self forKeyPath:@"rate"];