2009-03-29 15 views
26

Tengo un par de vistas que acceden al reproductor de películas. He puesto el siguiente código en un método en AppDelegate para estas vistas. Ellos envían el nombre del archivo para jugar. El código funciona bien, pero sé que se necesita una versión en algún lugar. Si agrego la última línea como un lanzamiento o liberación automática, la aplicación se bloqueará una vez que el usuario presiona sobre el reproductor.¿Cómo liberar MPMoviePlayerController?

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

me sale este error:

objc [51051]: LIBERADO (id): mensaje enviado a videoViewController objeto liberado = 0x1069b30

Programa recibió la señal: “EXC_BAD_INSTRUCTION”.

¿Cómo debo liberar el reproductor?

Respuesta

18

Lo que he encontrado es que al MPMoviePlayerController se le debe enviar el mensaje de detención antes de poder soltarlo con seguridad. Entonces lo hago en handlePlaybackEnd - primero lo detengo, luego lo cierro automáticamente. Llamando liberación no parece funcionar muy bien:

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

todo se vuelve un poco más complicado en el que el MPMoviePlayerPlaybackDidFinishNotification puede conseguir enviado más de una vez, pero llamar Parada/autorlease dos veces no le hará ningún bien . Entonces necesitas protegerte contra eso de alguna manera.

Por último, parece tomar algunas iteraciones del ciclo de ejecución principal hasta que pueda crear de forma segura una nueva instancia de MPMoviePlayerController. Si lo haces demasiado rápido, obtendrás sonido pero no video. Muy divertido, ¿eh?

+0

Sí, ya obtuve el sonido/nada de video. ¡Increíble!¿Cómo se protege contra múltiples notificaciones? ¿Se bloqueará si manejas múltiples? – 4thSpace

+0

Deberá tener algún tipo de bandera: si no está configurada, configúrela y suelte el reproductor. Si está configurado, no hagas nada. –

+4

Probablemente también podría almacenar MPMoviePlayerController como un ivar en el delegado. En el método moviePlaybackDidFinish: puede liberar el ivar y establecerlo en cero en lugar de acceder a notification.object. La segunda notificación enviará stop y autorelease a cero, lo cual está bien. –

7

Para contestar el comentario de 4thSpace en la respuesta anterior, se puede quitar el observador notificación, de modo que no lo recibe en múltiples ocasiones:

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

He intentado esto, pero mi consumo de memoria no baja? ¿eso significa que la memoria aún no se ha lanzado? – Nnp

2

Detener y la liberación no era suficiente para mí si el jugador no alcanzó hasta su final

Mi solución es establecer el moviePlayer.initialPlaybackTime = -1 en el moviePlayBackDidFinish: antes de soltarlo:

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

que tenían el mismo problema y me he dado cuenta de que puse el método de notificación con el objeto: cero (era un copiar y pegar) .

Tenía varias notificaciones, aunque no debería haber recibido ninguna notificación.

Aquí se ajusta a mi nueva notificación hasta el código que fija todos (ver el objeto: MoviePlayer):

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

Espero que ayude. Ahora todo mi código está funcionando correctamente.

3

para iphone os 3.2 necesita llamar al [moviePlayer pausa]; antes de llamar al [moviePlayer stop];

+0

¡gracias por esto! ¡Se estaba volviendo loco por el tema! – lostInTransit

+0

¡Gracias! Soportar viejas versiones del sistema operativo puede ser tan doloroso. –

0

Esto pareció reducir la memoria significativamente. Sin embargo, para iOS 4.1 parece estar bien.

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