12

Sto provando a riprodurre un MP3 tramite AVAudioPlayer che ho pensato fosse abbastanza semplice. Sfortunatamente, non sta funzionando. Ecco tutto quello che ho fatto:AVAudioPlayer interrompe la riproduzione immediatamente con ARC

  • Per motivi di test, ho creato una nuova applicazione iOS (Single View) in Xcode.
  • ho aggiunto il quadro AVFoundation al progetto così come il #import <AVFoundation/AVFoundation.h> al ViewController.m

  • ho aggiunto un file MP3 alla cartella Applicazioni 'Documenti'.

  • ho cambiato il ViewControllersviewDidLoad: al seguente:

Codice:

- (void)viewDidLoad 
{ 
    [super viewDidLoad];   

    NSString* recorderFilePath = [NSString stringWithFormat:@"%@/MySound.mp3", [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]];  

    AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:recorderFilePath] error:nil]; 
    audioPlayer.numberOfLoops = 1; 

    [audioPlayer play]; 

    //[NSThread sleepForTimeInterval:20]; 
} 

Purtroppo, l'audio si interrompe, ovviamente, subito dopo inizia a suonare. Se taccio il commento, il sleepForTimeInterval suona per 20 secondi e si ferma in seguito. Questo problema si verifica solo durante la compilazione con ARC, altrimenti funziona perfettamente.

+0

Non è necessario avviare un'altra discussione per riprodurre l'audio. Hai provato a fornire un puntatore di errore per vedere se qualcosa è stato registrato? – isaac

+0

che errore stai ottenendo? – Daniel

+0

Sì, ho passato un NSError a initWithContensOfURL. Rimane nullo, però ... Quindi non ricevo errori, smette solo di giocare immediatamente. – Phlibbo

risposta

7

Il problema è che quando si compila con ARC è necessario assicurarsi di mantenere un riferimento a istanze che si desidera conservare vivo come il compilatore automaticamente correggere "sbilanciato" alloc inserendo release chiamate (almeno concettualmente, leggere Mikes Ash blog post for more details). Puoi risolvere questo assegnando l'istanza a una proprietà oa una variabile di istanza.

Nel caso Phlibbo codice si trasformerà in:

- (void)viewDidLoad 
{ 
    [super viewDidLoad];   
    NSString* recorderFilePath = [NSString stringWithFormat:@"%@/MySound.mp3", [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]];  
    AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:recorderFilePath] error:nil]; 
    audioPlayer.numberOfLoops = 1; 
    [audioPlayer play]; 
    [audioPlayer release]; // inserted by ARC 
} 

E la AVAudioPlayer che verrà smettere di giocare immediatamente, come si arriva deallocata quando viene lasciato alcun riferimento.

Non ho usato ARC da solo e ho appena letto su di esso brevemente. Si prega di commentare la mia risposta se ne sapete di più e lo aggiornerò con ulteriori informazioni.

Maggiori informazioni ARC:
Transitioning to ARC Release Notes
LLVM Automatic Reference Counting

+0

Hai assolutamente ragione. Come detto nei commenti sopra. ;) – yinkou

+0

Non uso ARC e ho cercato di riprodurre suoni brevi nello stesso modo in cui scrivi. Sento solo il primo suono (e grazie a un bug di AVAudioPlayer che emette la prima volta un suono). Quindi nel migliore dei casi il tuo codice taglia i primi secondi di un audio, nel peggiore dei casi smette di suonare prima che il suono venga fermato da solo. – Gargo

+0

@Gargo: come, scrive Mattias nel suo post, il codice spiega perché il giocatore non ha funzionato nel mio caso, è intenzionalmente difettoso. Si dovrebbe guardare un tutorial di AVAudioPlayer, se non si ha esperienza con esso. – Phlibbo

3

Utilizzare l'AVAudioPlayer come Ivar nel file di intestazione con strong:

@property (strong,nonatomic) AVAudioPlayer *audioPlayer 
3

Se avete bisogno di più AVAudioPlayers che giocano allo stesso tempo, creare un NSMutableDictionary. Imposta la chiave come nome file. Rimuovi dal Dizionario tramite Delegata richiamata in questo modo:

-(void)playSound:(NSString*)soundNum { 


    NSString* path = [[NSBundle mainBundle] 
         pathForResource:soundNum ofType:@"m4a"]; 
    NSURL* url = [NSURL fileURLWithPath:path]; 

    NSError *error = nil; 
    AVAudioPlayer *audioPlayer =[[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error]; 

    audioPlayer.delegate = self; 

    if (_dictPlayers == nil) 
     _dictPlayers = [NSMutableDictionary dictionary]; 
    [_dictPlayers setObject:audioPlayer forKey:[[audioPlayer.url path] lastPathComponent]]; 
    [audioPlayer play]; 

} 

-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {   
    [_dictPlayers removeObjectForKey:[[player.url path] lastPathComponent]]; 
} 
+0

Questa è la soluzione migliore per riprodurre suoni contemporaneamente. Se utilizzi AVAudioPlayer come proprietà, l'oggetto verrà rilasciato quando suonerai il suono successivo e alcune persone stanno utilizzando AudioServicesPlaySystemSound ma Apple rifiuta le app perché continuerà a essere riprodotto quando il dispositivo è disattivato e non ci sono apici per controllare se il dispositivo è disattivato sordina. – Zeeshan

Problemi correlati