web-dev-qa-db-ja.com

MPMoviePlayerControllerを解放する方法は?

映画プレーヤーにアクセスするビューがいくつかあります。これらのビューの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」。

プレーヤーをどのようにリリースする必要がありますか?

26
4thSpace

私が見つけたのは、MPMoviePlayerControllerを安全に解放する前に、停止メッセージを送信する必要があるということです。だから私はhandlePlaybackEndでそれを行います-最初にそれを停止し、次にそれを自動解放します。リリースの呼び出しはあまりうまく機能していないようです:

- (void) moviePlayBackDidFinish : (NSNotification *) notification
{
  VideoPlayerController * player = notification.object;
  [player stop];
  [player autorelease];
}

MPMoviePlayerPlaybackDidFinishNotificationが複数回送信される可能性があるという点で、全体が少しトリッキーになりますが、stop/autorleaseを2回呼び出しても、何の役にも立ちません。だから、どういうわけかそれを防ぐ必要があります。

最後に、新しいMPMoviePlayerControllerインスタンスを安全に作成できるようになるまで、メインの実行ループを数回繰り返す必要があるようです。速すぎると音は出ますがビデオは出ません。とても楽しいですよね?

18
unwesen

上記の回答に対する4thSpaceのコメントに回答するには、通知オブザーバーを削除して、複数回受信しないようにすることができます。

- (void)moviePlayBackDidFinish:(NSNotification *)notification {
    MPMoviePlayerController *theMovie = [notification object];
    [[NSNotificationCenter defaultCenter] removeObserver:self
        name:MPMoviePlayerPlaybackDidFinishNotification
        object:theMovie];
    [theMovie stop];
    [theMovie release];
}
7
davidcann

iphone os 3.2の場合、[moviePlayerpause]を呼び出す必要があります。 [moviePlayerstop]を呼び出す前;

3
Mohan

プレイヤーが最後まで到達しなかった場合、停止して解放するだけでは十分ではありませんでした。

私の解決策は、リリースする前にmoviePlayer.initialPlaybackTime = -1moviePlayBackDidFinish:に設定することです。

-(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]; 
}
2
Tiger

これにより、メモリが大幅に削減されたようです。ただし、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];    
}
0
woot586

同じ問題が発生し、object:nil(コピーアンドペースト)で通知メソッドを設定したことに気付きました。

通知がまったくないはずなのに、複数の通知がありました。

これがすべてを修正した私の新しい通知セットアップコードです(object:moviePlayerを参照):

[[NSNotificationCenter defaultCenter] addObserver:self 
                           selector:@selector(moviePlaybackDidFinish:) 
                           name:MPMoviePlayerPlaybackDidFinishNotification 
                           object:moviePlayer]; 

お役に立てば幸いです。これで、すべてのコードが正しく機能しています。

0
mentat