AVAudioPlayer已取消分配,而键值观察者仍在注册

时间:2013-10-23 11:54:18

标签: ios objective-c avaudioplayer avplayer

-(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> )

我做错了什么?

2 个答案:

答案 0 :(得分:6)

您必须从观察者中删除self。当您致电-stop时,AVAudioPlayer的实例将被取消分配(您创建一个新实例)。但是你试图继续保留其价值观。

因此,您尝试观察内存中不再存在的实例。

试试这个:

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

    // and so on
}

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

答案 1 :(得分:1)

删除观察者后将avPlayerLayer设置为nil

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

在viewdisappear中检查avPlayerLayer不是nil然后删除observer

if (avPlayerLayer)
{
    [avPlayerLayer removeObserver:self forKeyPath:@"readyForDisplay"];
}