AVAudioPlayer перестает играть сразу с ARC

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

  • Для тестирования я создал новое приложение для iOS (Single View) в 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, в противном случае она работает безупречно.

Ответ 1

Проблема заключается в том, что при компиляции с ARC вам необходимо следить за экземплярами, которые вы хотите сохранить в качестве компилятора автоматически установит "неуравновешенный" alloc, вставив release вызовы (по крайней мере, концептуально, прочитайте

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

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

Дополнительная информация ARC:

Ответ 2

Используйте AVAudioPlayer как ivar в файле заголовка с strong:

@property (strong,nonatomic) AVAudioPlayer *audioPlayer

Ответ 3

Если вам нужно несколько AVAudioPlayers, играющих одновременно, создайте 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]];
}