AVAudioPlayer 被解除分配,而键值观察者仍向其注册

Posted

技术标签:

【中文标题】AVAudioPlayer 被解除分配,而键值观察者仍向其注册【英文标题】:AVAudioPlayer was deallocated while key value observers were still registered with it 【发布时间】:2013-10-23 11:54:18 【问题描述】:
-(void) setupAVPlayerForURL:(NSString *)url

    [appdelegate.sharedplayer stop];

    appdelegate.sharedplayer=[[AVAudioPlayer alloc] initWithContentsOfURL:url1 error:NULL];
    [[AVAudiosession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
    [[AVAudioSession sharedInstance] setActive: YES error: nil];
    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];

    [appdelegate.sharedplayer setVolume:appdelegate.volumeDelegate];

    [appdelegate.sharedplayer play];
    self.seekBarSlider.minimumValue = 0.0f;
    self.seekBarSlider.maximumValue = appdelegate.sharedplayer.duration;
    self.isPlaying=YES;
    appdelegate.sharedplayer.delegate=self;

    [self loadAlbumArt];
    [appdelegate.sharedplayer  addObserver:self forKeyPath:@"status" options:0 context:nil];

除了第一次运行此应用程序时,我都会收到此日志消息但应用程序没有崩溃

An instance 0xc1693d0 of class AVAudioPlayer was deallocated while key value observers were still registered with it. 
Observation info was leaked, and may even become mistakenly attached to some other object. Set a breakpoint on  NSKVODeallocateBreak to stop here in the debugger. 

这是当前的观察信息:

<NSKeyValueObservationInfo 0xc194d90> (
 <NSKeyValueObservance 0xc194e40: Observer: 0xc1697d0, Key path:
 status, Options: <New: NO, Old: NO, Prior: NO>         Context: 0x0,
 Property: 0xc194d70> )

我做错了什么??

【问题讨论】:

【参考方案1】:

您必须从观察者中删除self。当您调用 -stop 时,AVAudioPlayer 的实例将被释放(您创建一个新实例)。但你试图继续保留它的价值。

所以你尝试观察一个不再存在于内存中的实例。

试试这个:

- (void)setupAVPlayerForURL:(NSURL *)url 
    [[appdelegate sharedplayer] removeObserver:self];
    [[appdelegate sharedplayer] stop];

    // and so on

您的应用不会因为您访问已释放的实例而崩溃。 而是系统“崩溃”了您的应用程序,因为被观察对象的内存地址(然后被释放)可能稍后会指向其他对象,这会导致错误的观察消息被分派给您的观察者。

【讨论】:

【参考方案2】:

移除观察者后设置avPlayerLayer为nil

[avPlayerLayer removeObserver:self forKeyPath:@"readyForDisplay"];
 avPlayerLayer=nil;

在 viewdisappear 检查 avPlayerLayer 不是 nil 然后删除观察者

if (avPlayerLayer)

    [avPlayerLayer removeObserver:self forKeyPath:@"readyForDisplay"];

【讨论】:

以上是关于AVAudioPlayer 被解除分配,而键值观察者仍向其注册的主要内容,如果未能解决你的问题,请参考以下文章

类的实例被解除分配,而键值观察者仍向其注册

iOS 5 AVPlayerItem 的一个实例被释放

facebook ios sdk 日志:奇怪的消息

Objective-C 删除某个通知的所有观察者

PromiseKit 没有回调/解除分配? (阿拉莫菲尔)

KVO AVAudioPlayer 不工作