AVPlayer was deallocated while key value observers were still registered with it

时光毁灭记忆、已成空白 提交于 2019-12-02 17:04:24

I had a similar problem. It worked fine in iOS 7, and now it crashes in iOS 8.

The solution was to remove the observer, before releasing the object.

When you replace or allocate a new object for a member, you're releasing the old object, so you need to remove the observer first :

-(void) setupAVPlayerForURL: (NSURL*) url1 {
    AVAsset *asset = [AVURLAsset URLAssetWithURL:url1 options:nil];
    AVPlayerItem *anItem = [AVPlayerItem playerItemWithAsset:asset];
    if (player != nil)
        [player removeObserver:self forKeyPath:@"status"];
    player = [AVPlayer playerWithPlayerItem:anItem]; 
    [player addObserver:self forKeyPath:@"status" options:0 context:nil];
}

And similarly in btnPlayClick ( in case it is pressed without btnStop_Click being pressed) :

- (IBAction)btnPlay_Click:(id)sender {
     if (player != nil && [player currentItem] != nil)
         [[player currentItem] removeObserver:self forKeyPath:@"timedMetadata"];
    AVPlayerItem *item = player.currentItem;
    [item addObserver:self forKeyPath:@"timedMetadata" options:NSKeyValueObservingOptionInitial|     NSKeyValueObservingOptionNew| NSKeyValueObservingOptionOld| NSKeyValueObservingOptionPrior context:nil];
    [player play];
}
-(void)viewWillDisappear:(BOOL)animated
{
[self.player removeObserver:self forKeyPath:@"status" context:nil];
}

When using KVO you must balance calls to addObserver:forKeyPath:options:context: with calls to removeObserver:forKeyPath: (see the KVO programming guide).

Try removing the view controller as an observer when the stop button is tapped e.g.

- (IBAction)btnStop_Click:(id)sender {
    [[player currentItem] removeObserver:self forKeyPath:@"timedMetadata"];
}

I did meet the similar issue when using AVPlayer, the crash log info says:

An instance 0x174034600 of class AVKeyPathFlattener was deallocated while key value observers were still registered with it. Current observation info: ( Context: 0x0, Property: 0x17405d6d0> )

As what Apple recommended, what I originally did is adding observer after initialize my AVPlayerItem object, and remove observer in the observer's dealloc method. Because my observer class kept a strong reference on my AVPlayerItem object, so it should not be deallocated before my observer object was deallocated. I really don't know why this happens.

So I tried solved this problem by using BlocksKit, it works fine for me right now.

It's wise to verify first if the key is being observed or not before removing the observer with a @try @catch, like so:

@try {
    [self.player removeObserver:self forKeyPath:@"status" context:nil];
} @catch (id anException) {
    //do nothing, obviously it wasn't attached because an exception was thrown
    NSLog(@"status key not being observed");
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!