AVAudioPlayer перестает играть сразу с ARC - PullRequest
12 голосов
/ 08 октября 2011

Я пытаюсь воспроизвести MP3 через AVAudioPlayer, что мне показалось довольно простым. К сожалению, это не совсем работает. Вот все, что я сделал:

  • Ради тестирования я создал новое приложение для iOS (Single Посмотреть) в Xcode.
  • Я добавил инфраструктуру AVFoundation к проекту, а также #import <AVFoundation/AVFoundation.h> к ViewController.m

  • Я добавил MP3-файл в папку «Документы» приложения.

  • Я изменил ViewControllers viewDidLoad: на следующее:

Код:

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

К сожалению, звук, очевидно, останавливается сразу после начала воспроизведения. Если я раскомментирую sleepForTimeInterval, он будет проигрываться в течение 20 секунд, а затем останавливается. Эта проблема возникает только при компиляции с ARC, в противном случае она работает безупречно.

Ответы [ 3 ]

7 голосов
/ 12 октября 2011

Проблема в том, что при компиляции с ARC вам необходимо сохранять ссылку на экземпляры, которые вы хотите сохранить в живых, поскольку компилятор автоматически исправит "несбалансированный" alloc, вставив release звонки (по крайней мере, концептуально, прочитайте сообщение в блоге Майка Эша для более подробной информации ).Вы можете решить эту проблему, назначив экземпляр свойству или переменной экземпляра.

В случае Phlibbo код будет преобразован в:

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

И AVAudioPlayer прекратит воспроизведениесразу же, как он освобождается, когда не осталось никаких ссылок.

Я сам не использовал ARC и только что кратко прочитал об этом.Пожалуйста, прокомментируйте мой ответ, если вы знаете больше об этом, и я обновлю его с дополнительной информацией.

Дополнительная информация о ARC:
Переход к заметкам о выпуске ARC
LLVM Автоматический подсчет ссылок

3 голосов
/ 10 июля 2013

Если вам нужно одновременно играть несколько AVAudioPlayer, создайте NSMutableDictionary.Установите ключ в качестве имени файла.Удалить из словаря с помощью делегирования обратного вызова следующим образом:

-(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]];
}
3 голосов
/ 31 марта 2012

Используйте AVAudioPlayer в качестве ивара в заголовочном файле с strong:

@property (strong,nonatomic) AVAudioPlayer *audioPlayer
...