映画プレーヤーにアクセスするビューがいくつかあります。これらのビューのAppDelegateのメソッドに次のコードを配置しました。彼らは再生するファイル名を送信します。コードは正常に機能しますが、どこかにリリースが必要であることはわかっています。最後の行をリリースまたは自動リリースとして追加すると、ユーザーがムービープレーヤーで[完了]を押すとアプリがクラッシュします。
MPMoviePlayerController *moviePlayer = [[MPMoviePlayerController alloc]
initWithContentURL:[NSURL fileURLWithPath:moviePath]];
moviePlayer.movieControlMode = MPMovieControlModeDefault;
[moviePlayer play];
//[moviePlayer release];
このエラーが発生します:
objc [51051]:FREED(id):解放されたオブジェクトに送信されたメッセージvideoViewController = 0x1069b30
プログラム受信信号:「EXC_BAD_INSTRUCTION」。
プレーヤーをどのようにリリースする必要がありますか?
私が見つけたのは、MPMoviePlayerControllerを安全に解放する前に、停止メッセージを送信する必要があるということです。だから私はhandlePlaybackEndでそれを行います-最初にそれを停止し、次にそれを自動解放します。リリースの呼び出しはあまりうまく機能していないようです:
- (void) moviePlayBackDidFinish : (NSNotification *) notification
{
VideoPlayerController * player = notification.object;
[player stop];
[player autorelease];
}
MPMoviePlayerPlaybackDidFinishNotificationが複数回送信される可能性があるという点で、全体が少しトリッキーになりますが、stop/autorleaseを2回呼び出しても、何の役にも立ちません。だから、どういうわけかそれを防ぐ必要があります。
最後に、新しいMPMoviePlayerControllerインスタンスを安全に作成できるようになるまで、メインの実行ループを数回繰り返す必要があるようです。速すぎると音は出ますがビデオは出ません。とても楽しいですよね?
上記の回答に対する4thSpaceのコメントに回答するには、通知オブザーバーを削除して、複数回受信しないようにすることができます。
- (void)moviePlayBackDidFinish:(NSNotification *)notification {
MPMoviePlayerController *theMovie = [notification object];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:theMovie];
[theMovie stop];
[theMovie release];
}
iphone os 3.2の場合、[moviePlayerpause]を呼び出す必要があります。 [moviePlayerstop]を呼び出す前;
プレイヤーが最後まで到達しなかった場合、停止して解放するだけでは十分ではありませんでした。
私の解決策は、リリースする前にmoviePlayer.initialPlaybackTime = -1
をmoviePlayBackDidFinish:
に設定することです。
-(void)playMovie: (NSString *)urlString{
movieURL = [NSURL URLWithString:urlString];
moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
moviePlayer.initialPlaybackTime = 0;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlayBackDidFinish: ) name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayer] ;
moviePlayer.scalingMode = MPMovieScalingModeAspectFit;
moviePlayer.movieControlMode = MPMovieControlModeDefault;
moviePlayer.backgroundColor = [UIColor blackColor];
[moviePlayer play];
}
-(void)moviePlayBackDidFinish: (NSNotification*)notification{
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayer] ;
moviePlayer.initialPlaybackTime = -1;
[moviePlayer stop];
[moviePlayer release];
}
これにより、メモリが大幅に削減されたようです。ただし、IOS 4.1の場合は、問題ないようです。
- (void)videoFinishedCallback:(NSNotification *)aNotification
{
thePlayer = [aNotification object];
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification object:thePlayer];
thePlayer.initialPlaybackTime = -1;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200
[thePlayer pause];
#endif
[thePlayer stop];
[thePlayer release];
}
同じ問題が発生し、object:nil(コピーアンドペースト)で通知メソッドを設定したことに気付きました。
通知がまったくないはずなのに、複数の通知がありました。
これがすべてを修正した私の新しい通知セットアップコードです(object:moviePlayerを参照):
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(moviePlaybackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayer];
お役に立てば幸いです。これで、すべてのコードが正しく機能しています。