2009-03-29 9 views
26

Mam kilka widoków, które mają dostęp do odtwarzacza filmów. Dla tych widoków umieściłem następujący kod w metodzie w AppDelegate. Wysyłają nazwę pliku do odtworzenia. Kod działa dobrze, ale wiem, że gdzieś jest wymagane wydanie. Jeśli dodaję ostatnią linię jako wydanie lub autooddzielanie, aplikacja zawiesi się po naciśnięciu przycisku użytkownika na odtwarzaczu filmów.Jak zwolnić MPMoviePlayerController?

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

otrzymuję ten błąd:

objc [51051]: Freed (id): Komunikat videoViewController wysłany do wyzwolonego obiektu = 0x1069b30

Program otrzymał sygnał: „EXC_BAD_INSTRUCTION”.

Jak mam zwolnić odtwarzacz?

Odpowiedz

18

To, co znalazłem, to to, że MPMoviePlayerController musi otrzymać komunikat o zatrzymaniu, zanim będzie można bezpiecznie go zwolnić. Robię to w handlePlaybackEnd - najpierw go zatrzymuję, potem autoreasuję. Wywołanie uwalnianie nie wydaje się zbyt dobrze:

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

Cała sprawa staje się nieco trudniejsze, że MPMoviePlayerPlaybackDidFinishNotification można wysyłane więcej niż raz, ale nazywając przystanek/autorlease dwukrotnie nie będzie Pan jakieś dobre albo . Więc musisz jakoś się przed tym uchronić.

Wreszcie, wydaje się, że trzeba wykonać kilka iteracji pętli głównej, dopóki nie będzie można bezpiecznie utworzyć nowej instancji MPMoviePlayerController. Jeśli zrobisz to zbyt szybko, otrzymasz dźwięk, ale nie wideo. Świetna zabawa, co?

+0

Taa ... Mam już dźwięk/brak wideo. Niesamowite!Jak chronić się przed wieloma powiadomieniami? Czy ulegnie awarii, jeśli będziesz obsługiwać wiele? – 4thSpace

+0

Musisz mieć jakąś flagę: jeśli nie jest ustawiona, ustaw ją i zwolnij gracza. Jeśli jest ustawiony, nie rób nic. –

+4

Prawdopodobnie możesz również przechowywać MPMoviePlayerController jako ivar w delegacie. W metodzie moviePlaybackDidFinish: można zwolnić ivar i ustawić go na zero zamiast dostępu do powiadomienia.object. Drugie powiadomienie wyśle ​​stop i autorelease do zera, co jest w porządku. –

7

Aby odpowiedzieć na komentarz 4thSpace w sprawie odpowiedzi powyżej, można usunąć obserwatora powiadamiania więc nie otrzyma go wielokrotnie:

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

próbowałem tego, ale moje zużycie pamięci nie zejdzie? Czy to oznacza, że ​​pamięć nie jest jeszcze wydana? – Nnp

2

zatrzymywanie i zwalnianie nie było dla mnie za mało, jeśli gracz nie osiągnął do końca.

Moje rozwiązanie jest ustawienie moviePlayer.initialPlaybackTime = -1 w moviePlayBackDidFinish: przed wypuszczeniem go:

-(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

miałem ten sam problem i po prostu sobie sprawę, że ustawienie sposobu powiadamiania o obiekcie: nil (było pasty kopia) .

Otrzymałem wiele powiadomień, chociaż nie powinienem był otrzymywać żadnych powiadomień.

Oto mój nowy powiadomienie ustawić kod stały wszystko (patrz obiektu: movieplayer):

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

nadzieję, że pomoże. Teraz cały mój kod działa poprawnie.

3

dla iPhone OS 3.2 musisz zadzwonić pod numer [pauza moviePause]; przed wywołaniem [moviePlayer stop];

+0

dziękuję za to! Szaleje nad tym problemem! – lostInTransit

+0

Dziękujemy! Obsługa starych wersji systemu operacyjnego może być bardzo bolesna. –

0

To wydawało się znacznie zmniejszyć pamięć. Jednak dla IOS 4.1 wydaje się to w porządku.

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