2009-03-29 4 views
26

Ich habe ein paar Ansichten, die auf den Movie-Player zugreifen. Ich habe den folgenden Code in eine Methode in AppDelegate für diese Ansichten eingefügt. Sie senden den Dateinamen zum Abspielen ein. Der Code funktioniert gut, aber ich weiß, dass eine Freigabe irgendwo erforderlich ist. Wenn ich die letzte Zeile als Release oder Autorelease hinzufüge, stürzt die App ab, sobald der Benutzer done auf dem Movieplayer drückt.Wie kann ich MPMoviePlayerController freigeben?

MPMoviePlayerController *moviePlayer = [[MPMoviePlayerController alloc] 
       initWithContentURL:[NSURL fileURLWithPath:moviePath]]; 
moviePlayer.movieControlMode = MPMovieControlModeDefault; 
[moviePlayer play]; 
//[moviePlayer release]; 

ich diesen Fehler:

objc [51051]: FREED (id): Nachricht videoViewController zu befreite Objekt gesendet = 0x1069b30

Programmsignal empfangen: „EXC_BAD_INSTRUCTION“.

Wie sollte ich den Player freigeben?

Antwort

18

Was ich gefunden habe ist, dass der MPMoviePlayerController die Stop-Nachricht gesendet werden muss, bevor Sie es sicher freigeben können. Also mache ich es in handlePlaybackEnd - zuerst höre ich es auf, dann veröffentliche ich es automatisch. Der Aufruf Release scheint nicht allzu gut zu funktionieren:

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

Das Ganze in ein bisschen schwieriger wird, dass die MPMoviePlayerPlaybackDidFinishNotification mehr gesendete kann als nur einmal, sondern ruft Stopp/autorlease zweimal wird dir nicht gut entweder tun . Also musst du dich davor schützen.

Schließlich scheint es einige Iterationen der Hauptlaufschleife zu geben, bis Sie sicher eine neue MPMoviePlayerController-Instanz erstellen können. Wenn Sie es zu schnell machen, erhalten Sie Ton, aber kein Video. Viel Spaß, nicht wahr?

+0

Yeah -Ich habe das Geräusch/keine Video-Sache schon. Genial!Wie schützen Sie sich vor Mehrfachbenachrichtigungen? Wird es abstürzen, wenn Sie mit mehreren umgehen? – 4thSpace

+0

Sie müssen eine Art Flagge haben: Wenn sie nicht gesetzt ist, stellen Sie sie ein und lassen Sie den Player los. Wenn es eingestellt ist, tu nichts. –

+4

Sie könnten den MPMoviePlayerController wahrscheinlich auch als Ivar im Delegaten speichern. In der moviePlaybackDidFinish: -Methode können Sie den ivar freigeben und auf nil setzen, anstatt auf notification.object zuzugreifen. Die zweite Benachrichtigung sendet Stopp und Autorelease an Null, was in Ordnung ist. –

7

Um 4thSpace Kommentar auf der Antwort oben, können Sie die Benachrichtigung Beobachter entfernen, damit Sie sie nicht mehrfach erhalten:

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

Ich habe das versucht, aber mein Speicherverbrauch geht nicht runter? Bedeutet das, dass Speicher noch nicht freigegeben ist? – Nnp

2

Stoppen und Freigeben war nicht genug für mich, wenn der Spieler nicht erreicht zu seinem Ende.

Meine Lösung ist an der moviePlayBackDidFinish: die moviePlayer.initialPlaybackTime = -1 Einstellung vor der Freigabe:

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

Ich hatte das gleiche Problem, und ich gerade erkannte ich die Benachrichtigungsmethode mit dem Objekt festgelegt: null (es war eine Kopie Paste) .

Ich hatte mehrere Benachrichtigungen, obwohl ich überhaupt keine Benachrichtigungen hätte haben sollen.

Hier ist meine neue Benachrichtigung einrichten Code, der alle festen (das Objekt sehen: Movieplayer):

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

Hoffnung, das hilft. Jetzt funktioniert mein Code einwandfrei.

3

für iphone os 3.2 müssen Sie anrufen [moviePlayer Pause]; vor dem Anruf [moviePlayer stop];

+0

danke dafür! War verrückt nach dem Thema! – lostInTransit

+0

Danke !!! Die Unterstützung alter Betriebssystemversionen kann so schmerzhaft sein. –

0

Dies schien den Speicher erheblich zu reduzieren. Für IOS 4.1 scheint das jedoch in Ordnung zu sein.

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