AVPlayer类的实例已被释放

时间:2014-08-15 16:57:32

标签: ios objective-c avplayer

我有UIView通过播放音频文件来响应单击手势。它通过使用AVPlayer类来完成此操作。一切都很好,有一个例外。如果用户当前正在收听音频文件,并且他们再次点击相同的UIView,我希望音频文件返回到开头并从头开始再次播放。但是,当发生这种情况时,我得到以下控制台输出:

  

类AVPlayer的实例0x10ad89dd0在键时被释放   价值观察员仍在注册。观察信息是   泄露,甚至可能被错误地附着在其他物体上。

我的游戏方法中的前三行是我试图解决这个问题,但他们没有解决任何问题。音频会重新启动,但控件(播放的时间,滑块等)都会变得疯狂。我看到其他几个帖子,我仍然卡住了。任何人都可以看到我需要做些什么来解决这个问题?

- (void) playAudio : (UITapGestureRecognizer *)recognizer
{

    // remove any existing observers to prevent memory leaks
    [self.audioPlayer pause];
    self.audioPlayer = nil;
    [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:self.audioPlayer];

    unsigned long buttonPressed = [self.buttonsArray indexOfObject:recognizer.view];

    Sessions *session = self.sessionsList[buttonPressed];
    self.mediaFile  = session.media_file;
    self.totalSecondsToPlay = [session.play_seconds integerValue];

    [self resetAVControls];

    NSString *urlString = [NSString stringWithFormat:@"%@%@", AUDIO_URL, self.mediaFile];
    AVPlayer *player = [[AVPlayer alloc]initWithURL:[NSURL URLWithString:urlString]];

    self.audioPlayer = player;

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(playerItemDidReachEnd:)
                                                 name:AVPlayerItemDidPlayToEndTimeNotification
                                               object:[self.audioPlayer currentItem]];

    [self.audioPlayer addObserver:self forKeyPath:@"status" options:0 context:nil];

    self.isPlaying = YES;

    timer = [NSTimer scheduledTimerWithTimeInterval:1.0
                                     target:self
                                   selector:@selector(updateProgress)
                                   userInfo:nil
                                    repeats:YES];


}

2 个答案:

答案 0 :(得分:3)

您已为self.audioPlayer注册了KeyValueObservers,但在将值设置为nil时,您尚未将其删除。因此,在self.audioPlayer = nil;使用[self.audioPlayer removeObserver:self forKeyPath:@"status" context:nil]

取消订阅KVO之前

Check this如果你想了解更多关于KVO

的信息

答案 1 :(得分:0)

每次将你的playerview设置为nil时,请先调用removeObserver。

实施例

[self removeObserverForStatusPlay];
playerView = nil;

在Init

之前
[self removeObserverForStatusPlay];
playerView = [[AVPlayer alloc] initWithURL:url];

当removeObserverForStatusPlay方法为

- (void)removeObserverForStatusPlay
{
    @try {
        [playerView removeObserver:self forKeyPath:@"status"];
    } @catch(id anException) {
        NSLog(@"excepcion remove observer == %@. Remove previously or never added observer.",anException);
        //do nothing, obviously it wasn't attached because an exception was thrown
    }
}