天天看點

iOS6下慎用MPMoviePlayerViewController!

這個MPMoviePlayerViewController的事要從何說起呢,嗯……其實主要還是由于在播放視訊時按Home鍵切出引發的問題:

先是測試發現遊戲在播放開場視訊時按Home鍵切換到背景後會觸發libGPUSupportMercury.dylib: gpus_ReturnNotPermittedKillClient導緻crash,關于這個異常大蘋果的Technical Q&A QA1766(http://developer.apple.com/library/ios/#qa/qa1766/_index.html)已經交待得很清楚了,簡單來說就是應用在處于背景狀态時是不允許執行任何OpenGL指令的,包括前台時送出但尚未實際執行的緩沖指令!不過文檔中提到的幾個關鍵點我也都按規矩做了處理,稍作跟蹤後發現,導緻這個異常的原因是在應用播放視訊時切到背景之後,MPMoviePlayerPlaybackDidFinishNotification通知被莫名其妙的觸發了,導緻後續邏輯按照開場視訊播放結束開始執行,進而去加載OpenGL貼圖,初始化狀态等,于是自然被OS認為是違規調用了OpenGL指令,是以被kill掉了!

随後,通過對MPMoviePlayerController的MPMoviePlayerPlaybackStateDidChangeNotification通知消息進行跟蹤後發現,當app切換到背景之後,MoviePlayer并沒有按照我之前所想的那樣,對尚未播放完成的視訊做了暫停操作(MPMoviePlaybackStatePaused狀态),而是直接切換到了MPMoviePlaybackStateStopped狀态,随後發出了視訊播放結束的通知!

既然如此,我就按照實際發生的情況,在AppDelegate的applicationWillResignActive:和applicationDidBecomeActive:消息中作了一下狀态處理,忽略掉應用背景時收到的視訊播放完成通知,這樣修改之後,背景調用GL指令的情況就沒再出現了。但是,随之而來的又發現了另一個問題,就是視訊播放過程中切出再切回來時視訊應該以繼續的方式接着播放,而由于之前測試發現的stop狀态,導緻每次應用切回來後都是從頭開始播放!搜尋一番後發現可以用MPMoviePlayerController的setInitialPlaybackTime:方法設定視訊初始播放時間,也就是說需要手動記錄視訊播放中斷時的時間,這個好辦,用一個NSTimeInterval儲存MPMoviePlaybackStatePaused或應用切出時的currentPlaybackTime即可。

滿心歡喜的改完後,卻發生了悲劇的事情:真機測試時,發現這種實作方式在iOS5裝置上沒有問題,雖然切回來時不一定能準确定位到中斷時的時間,但也會是在附近繼續播放,算是實作了預期的效果,可是在iOS6裝置上測試時,發現setInitialPlaybackTime:完全沒有起到作用,視訊依然是從頭播放!這個問題後來在cnrainbird的部落格中找到了一絲線索:http://blog.cnrainbird.com/index.php/2012/11/02/jiu_gong_cheng_shi_pei_ios6_he_iphone5_xu_zhi_mpmovieplayercontroller/,但我按照此篇博文裡的方式修改了一下後測試發現依然沒有效果!不管怎麼說,用MPMoviePlayerViewController時的setInitialPlaybackTime在iOS6上不起作用這已經是個不争的事實了,也許是bug!

搜尋各種論壇,翻各種部落格後,無意間發現了大蘋果官方的MoviePlayer示例程式:http://developer.apple.com/library/ios/#samplecode/MoviePlayer_iPhone/Introduction/Intro.html,載下來替換成自己的視訊試了一下切出和切入,發現完全沒有問題,暫停和繼續的時間都和我現在的方法在iOS5裝置上看到的一樣,細看了一下代碼實作後,發現這個例子并沒有用MPMoviePlayerViewController而是自己實作了一個繼承自UIViewController的封裝了MPMoviePlayerController的自定義視圖控制器,随後斷點跟蹤了一下例子裡的代碼執行邏輯,發現程式切出後,通知回掉并沒有像我之前的做法那樣收到MPMoviePlaybackStateStopped狀态通知(同時也沒有播放完成的通知!),而就是所想的MPMoviePlaybackStatePaused狀态,當然,這些都是在iOS6裝置上測試的。繼續看代碼後發現,示例程式也沒有對applicationWillResignActive:和applicationDidBecomeActive:或類似消息做什麼特殊處理。是以斷定:iOS6下慎用MPMoviePlayerViewController!

替換掉了原來的MoviePlayer視訊播放邏輯實作方式,改為和大蘋果例子一樣的自定義視圖控制器封裝MPMoviePlayerController的做法後,之前的問題得到了比較完美的解決!

轉載:http://blog.k-res.net/archives/1193.html