2009-03-29 13 views
26

Ho un paio di viste che accedono al riproduttore di film. Ho inserito il seguente codice in un metodo in AppDelegate per queste viste. Mandano il nome del file per giocare. Il codice funziona bene, ma so che è necessaria una versione da qualche parte. Se aggiungo l'ultima riga come release o autorelease, l'app si arresta in modo anomalo una volta che l'utente ha premuto sul filmplayer.Come rilasciare MPMoviePlayerController?

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

ottengo questo errore:

objc [51051]: LIBERATO (id): messaggio inviato a videoViewController oggetto liberato = 0x1069b30

programma ha ricevuto il segnale: “EXC_BAD_INSTRUCTION”.

Come devo rilasciare il lettore?

risposta

18

Quello che ho trovato è che MPMoviePlayerController deve essere inviato il messaggio di arresto prima di poterlo rilasciare in sicurezza. Quindi lo faccio in handlePlaybackEnd - prima lo interrompo, quindi lo autorizzo automaticamente. La chiamata di rilascio non sembra funzionare troppo bene:

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

Il tutto diventa un po 'più complicato in quanto il MPMoviePlayerPlaybackDidFinishNotification può ottenere inviato più di una volta, ma chiamando arresto/autorlease due volte non farà nulla di buono neanche . Quindi devi proteggerti in qualche modo.

Infine, sembra che siano necessarie alcune iterazioni del ciclo di esecuzione principale finché non è possibile creare in modo sicuro una nuova istanza MPMoviePlayerController. Se lo fai troppo velocemente, otterrai l'audio ma non il video. Molto divertente, eh?

+0

Sì, ho già ricevuto il suono/nessun video. Eccezionale!Come ti guardi dalle notifiche multiple? Crollerà se gestisci più? – 4thSpace

+0

Dovrai avere una sorta di flag: se non è impostato, impostalo e rilascia il player. Se è impostato, non fare nulla. –

+4

Probabilmente si potrebbe anche memorizzare MPMoviePlayerController come un ivar nel delegato. Nel metodo moviePlaybackDidFinish: puoi rilasciare ivar e impostarlo su nil invece di accedere a notification.object. La seconda notifica invierà stop e autorelease a zero, il che va bene. –

7

Per rispondere a un commento di 4thSpace sulla risposta di cui sopra, è possibile rimuovere l'osservatore di notifica in modo da non lo ricevete più volte:

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

ho provato questo, ma il mio consumo di memoria non diminuisce? vuol dire che la memoria non è ancora stata rilasciata? – Nnp

2

Arresto e rilasciando non era abbastanza per me, se il giocatore non ha raggiunto alla sua fine

La mia soluzione è l'impostazione del moviePlayer.initialPlaybackTime = -1 al moviePlayBackDidFinish: prima di rilasciarlo:

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

Ho avuto lo stesso problema e ho appena realizzato ho impostato il metodo di notifica con l'oggetto: nullo (si trattava di una copia incolla) .

Avevo più notifiche, anche se non avrei dovuto ricevere alcuna notifica.

Qui è impostata la mia nuova notifica aggiornata codice che fissa tutti (vedi l'oggetto: MoviePlayer):

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

Speranza che aiuta. Ora tutto il mio codice funziona correttamente.

3

per iphone os 3.2 è necessario chiamare [pausa filmPlayer]; prima di chiamare [fermata moviePlayer];

+0

grazie per questo! Stavo impazzendo per il problema! – lostInTransit

+0

Grazie !!! Il supporto delle vecchie versioni del sistema operativo può essere così doloroso. –

0

Questo sembrava ridurre significativamente la memoria. Tuttavia per IOS 4.1 sembra soddisfacente.

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