2

У меня есть класс, который я называю использовать AVAudioPlayer и все работает нормально, и денди, когда речь идет о воспроизведении аудио, но когда -audioPlayerDidFinishPlaying: называется моя NSLog() команды говорит, что игрок освобождается; проблема в том, что приложение выйдет из строя через несколько секунд. Я должен отметить, что audioPlayer является ivar в этом классе. Вот код:EXC_BAD_ACCESS после audioPlayerDidFinishPlaying: называется

-(id) initWithFileName:(NSString *)sndFileName 
{ 
    [super init]; 
    sndFileToPlay = [[NSString alloc] initWithString:sndFileName]; 
    return self; 
} 

-(void)dealloc { 
    [audioPlayer release]; 
    self.audioPlayer.delegate = nil; 
    self.audioPlayer = nil; 
    [super dealloc]; 
} 

-(void)play 
{ 
    [self playSound:sndFileToPlay]; 
} 

-(void)playSound:(NSString *)fileName 
{ 
    NSString *fname, *ext; 
    NSRange range = [fileName rangeOfString:@"."]; 
    int location = range.location; 
    if(location > 0) 
    { 
     fname = [fileName substringWithRange:NSMakeRange(0, location)]; 
     ext = [fileName substringFromIndex:location+1]; 
     [self playSound:fname :ext]; 
    } 
} 

-

-(void)playSound:(NSString *)fileName :(NSString *)fileExt 
{ 
    NSBundle *mainBundle = [NSBundle mainBundle]; 

    NSURL *fileURL = [NSURL fileURLWithPath: 
      [mainBundle pathForResource:fileName ofType:fileExt] isDirectory:NO]; 

    if (fileURL != nil) 
    { 
     audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: fileURL 
                  error: nil]; 

     [fileURL release]; 
     [audioPlayer setDelegate:self]; 
     [audioPlayer play]; 
    } 
} 

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player 
         successfully:(BOOL)flag 
{ 
    NSLog(@"Releasing"); 
    [audioPlayer release]; 
} 
+0

Измените свой вопрос и исправьте форматирование. Благодарю. – DarkDust

ответ

4

Есть несколько вещей неправильно с вашим кодом.

С одной стороны, в вашем dealloc:

[audioPlayer release]; 
self.audioPlayer.delegate = nil; 
self.audioPlayer = nil; 

Вы выпускаете аудиоплеер, затем на (и, возможно, освобождаться) игрок выпустил вы установили делегат к нулю, а затем собственности, которая высвобождает снова. Удалите [audioPlayer release];.

В вашем audioPlayerDidFinishPlaying:successfully: вы также выпускаете плеер, но вы не установили переменную в nil. Это может привести к сбою, так как к тому моменту, когда вы снова получите доступ к этой переменной, на этот адрес памяти может быть другой объект. Используйте свойство вместо этого и сделать это как в вашем dealloc:

self.audioPlayer.delegate = nil; 
self.audioPlayer = nil; 

Тогда, в playSound:: вас более-релиз fileURL (Argh, не названного второго аргумента!). -[NSURL fileURLWithPath:isDirectory:] возвращает объект с автореализацией, вы не можете его освободить.

Последнее, но, возможно, не в последнюю очередь утечка sndFileToPlay, вам необходимо отпустить его в своем методе dealloc. И вместо sndFileToPlay = [[NSString alloc] initWithString:sndFileName]; просто сделайте sndFileToPlay = [sndFileName copy];.

Возможно, вы захотите ознакомиться с управлением памятью Objective-C. Это не сложно, если вы знаете три или четыре правила.

+0

Спасибо за руководство DarkDust. Я следил за вашими рекомендациями (а также назвал второй аргумент в playSound), и AVPlayer выпускается правильно и без каких-либо утечек. Я думаю, что последний гвоздь в гробу - это высвобождение файлаURL; после того как я удалил это из кода, он прошел довольно гладко. Еще раз спасибо! – dman

0

Вы должны очистить свой код. Если playSound вызывается несколько раз, вы пропускаете AVAudioPlayer.

В вашем dealloc вы должны поместить [audioPlayer release] после двух строк внизу.

Включите NSZombieEnabled для отладки и убедитесь, что аудиоплеер не освобожден при вызове метода didFinish.

+0

Привет Анди, спасибо за ввод. Я закончил удаление версии [audioPlayer release] из dealloc за рекомендацию DarkDust и исправил другие ошибки, которые он предложил, поэтому я собираюсь принять его ответ. – dman

Смежные вопросы