_moviePlayerDidBecomeActiveNotification错误的解决

原创
2015/07/16 17:56
阅读数 305

问题原因:

在APP制作时有一个需求是要在一个tableview里存在多个MPMoviePlayerController,同时会有一个隐藏的全局MPMoviePlayerController,当屏幕翻转全屏时,调用全局的MPMoviePlayerController。

当滑动tableview时,显示正中间的播放视频。

滑动切换时,要让前一个MPMoviePlayerController停止播放,并且为了缓解内存,要设置MPMoviePlayerController = nil。同时要让下一个要播放的MPMoviePlayerController开始准备播放。

这时快速滑动,并且来回切换某两个视频,有很大概率会崩溃在[self.moviewPlayController prepareToPlay]并且报出一条错误:

*****Assertion failure in -[MPMoviePlayerControllerNew _moviePlayerDidBecomeActiveNotification:], /SourceCache/MediaPlayer/MobileMusicPlayer-2770.3.5/SDK/MPMoviePlayerController.m:1385



问题分析:

_moviePlayerDidBecomeActiveNotification

这个错误明显是一个系统通知,而且这条通知是无法在公开API里查到的,那么这就是一个系统内部使用的通知,而且苹果官方认为这个通知不需要开发者控制。

通过查找相关问题和资料,找到一些可供参考的内容,先抛出相关资料

stackoverflow:

http://stackoverflow.com/questions/17302389/assertion-failure-in-mpmovieplayercontrollernew-movieplayerdidbecomeactivenot

http://stackoverflow.com/questions/6766074/assertion-failure-movie-player-has-wrong-activation-state-1

一个有关的邮件记录:

http://www.mail-archive.com/cocoa-dev@lists.apple.com/msg68041.html

如果你真的为这个bug,或者相关的问题困惑,请一定先看看这些资料。

有可能是以下原因:

  1. 当前一个MPMoviePlayerController被释放时,为了获得播放器的各种状态,添加了很多的系统通知,如MPMediaPlaybackIsPreparedToPlayDidChangeNotification这种。但是在更换MPMoviePlayerController时要移除这个通知,如果不添加具体是哪个播放器添加了这个通知,很可能会出现移除的是新播放器的通知信息

  2. 添加一段描述:
    After playing with it for a bit, I found that the player's loadState property 
    >is set to (MPMovieLoadStatePlayable | MPMovieLoadStatePlaythroughOK) when 
    >playback finishes normally or MPMovieLoadStateUnknown when it's stopped 
    >because another player instance has grabbed control. I've added a test that 
    >prevents the queueing if the loadState is MPMovieLoadStateUnknown and that 
    >seems to work just fine.
    
    大概翻译一下:
    当播放器播放结束时,或者LoadState处于MPMovieLoadStateUnknown状态时停止播放这个播放器,会出现我们已知的这个报错。原因也许就是新的播放器获得播放控制时,上一个播放器还处于激活状态,而新播放器调用play方法时再次激活出现错误。当在MPMovieLoadStateUnknown状态时添加相关判断后,播放器就正常了。

        其实MPMOovieLoadStateUnknown这个命名就很有趣,貌似上层封装时检查到了播放器会在停止,开始状态中间            处于一种未知的状态,而且这个状态会持续1秒左右,好像这个状态是切换系统播放状态的准备时间。在这个状态下调            用播放器的stop方法或者play方法会报错。


解决方案:

如果是情况1,按照这个模式添加系统通知,并且在移除时也添加object属性:

NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self
           selector:@selector(moviePlaybackStateChanged:) 
               name:MPMoviePlayerPlaybackDidFinishNotification 
            object:self.movieController];

如果是情况2,那么就要在具体报错的位置添加判断。比如我遇到这个地方就可以在prepareToPlay的地方添加判断,给系统2秒钟去修改这个状态(谁让咱不能自己改呢╮(╯_╰)╭):

    if(self.moviePlayerController.loadState == MPMovieLoadStateUnknown){
        [self.moviePlayerController performSelector:@selector(prepareToPlay) withObject:nil afterDelay:2];
    }
    else{
        [self.moviePlayerController prepareToPlay];
    }

同时在移除播放器,为了防止在移除时都还没有调用这个延迟两秒的prepareToPlay方法,别忘了添加cancel方法

  [NSObject cancelPreviousPerformRequestsWithTarget:self.moviePlayerController selector:@selector(prepareToPlay) object:nil];


以上,这个问题就解决的七七八八了,具体情况,等测试反馈咯。




展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
0
分享
返回顶部
顶部