2009-08-29 3 views
6

Я застрял в какой-то странной проблеме с утечкой памяти, связанной с AVAudioPlayer, и мне нужна помощь после того, как вы попробовали все, что пришло в голову.Ошибка утечки AVAudioPlayer

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

В этот момент (сразу после вызова нового игрока - [Player play]). Я получаю утечку памяти (3.5Kb).

Я попытался следующие:

  • Остановите старый проигрыватель, а затем отпустить его - никакого эффекта

  • Отпустить игрока сразу после команды игры - не заиграть

  • Выпуск дважды старого игрока - авария

  • Утечка памяти НЕ происходит, когда я создаю и играю первый игрок!

Кроме того, в ссылке он сказал, что «играть» является асинхронной и поэтому, вероятно, он увеличивает счетчик ссылок 1, но в этом случае, почему не сделал [остановить Player] помочь?

Спасибо,

Вот некоторые части кода о том, как я использую его:

- (void) loadAndActivateAudioFunction { 
NSBundle  *mainBundle = [NSBundle mainBundle]; 
NSError   *error; 
NSURL   *audioURL = [NSURL fileURLWithPath:[mainBundle pathForResource: Name ofType: Type]]; 
AVAudioPlayer *player = [(AVAudioPlayer*) [AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:&error]; 

if (!player) { 
    DebugLog(@"Audio Load Error: no Player: %@", [error localizedDescription]); 
    DuringAudioPrep = false; 
    return; 
} 
[self lock]; 
[self setAudioPlayer: player]; 
[self ActivateAudioFunction]; 
[self unlock]; 

}

- (void) setAudioPlayer : (AVAudioPlayer *) player { 
if (Player) 
{ 
    if ([Player isPlaying] || Repeat) // The indication was off??? 
     [Player stop]; 
    [Player release]; 
} 
Player = player; 

}

- (void) ActivateAudioFunction { 
[Player setVolume: Volume]; 
[Player setNumberOfLoops: Repeat];  
[Player play]; 

DuringAudioPrep = false; 

}

ответ

0

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

Я скажу, что вы используете своего рода странную идиому. Вместо того, чтобы сохранить на создание и отпустив на съемочной площадке, я бы что-то вроде этого:

// new players will always be created autoreleased. 
    AVAudioPlayer *player = [[(AVAudioPlayer*) [AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:&error] autorelease]; 

- (void) setAudioPlayer : (AVAudioPlayer *) player 
{ 
    if (Player) 
    { 
     if ([Player isPlaying] || Repeat) // The indication was off??? 
      [Player stop]; 
     [Player release]; 
    } 
    Player = [player retain]; 
} 

Таким образом, вы только сохранить «игрок» объекты, когда они на самом деле приходят в ваш метод setAudioPlayer, что может сделать его проще выслеживать.

Кроме того, убедитесь, что на самом деле это объект AVAudioPlayer, который протекает. Инструменты должны быть в состоянии проверить это для вас.

+0

Спасибо за ответ. Да - я проверял, что это AVAudioPlayer с инструментами. Что касается метода - я использую этот, потому что я фактически сохраняю разные треки и повторно использую их, сопоставляя имена и если они не играют (вместо того, чтобы загружать один и тот же трек несколько раз). Поскольку я знаю, что у меня есть Player от вызывающего абонента после выполнения «Alloc» на нем, я знаю, что он уже сохранен (если только я не ошибаюсь?) – Adi

7

Здесь вы можете создать AVAudioPlayer, не вызывая утечки памяти. See this page for explaination.

В моем приложении подтверждено, что это удалило мой AVAudioPlayer на 100%.

- (AVAudioPlayer *)audioPlayerWithContentsOfFile:(NSString *)path { 
    NSData *audioData = [NSData dataWithContentsOfFile:path]; 
    AVAudioPlayer *player = [AVAudioPlayer alloc]; 
    if([player initWithData:audioData error:NULL]) { 
     [player autorelease]; 
    } else { 
     [player release]; 
     player = nil; 
    } 
    return player; 
} 
+1

Я думаю, что это должно быть набрано NSData * audioData на втором line ... – SpaceDog

+0

Этот код действительно странный, нет причин для разделения вызовов alloc vs init. Для лучшего общего подхода см. Http://stackoverflow.com/questions/17603551/arc-forbids-autorelease/17604365#17604365 или вы можете просто добавить авторекламу в виде [[[AVAudioPlayer alloc] initWithData: ошибка аудиоданных: NULL] autorelease ] – MoDJ

-2

Попробуйте добавить MediaPlayer.framework к вашему проекту

+0

'MediaPlayer.framework'? 'AVAudioPlayer' находится в' AVFoundation.framework' и не требует 'MediaPlayer'. Поразмыслить? –

2

Реализация AVAudioPlayerDelegate протокола и его метод audioPlayerDidFinishPlaying: успешно: затем отпустите звуковой объект игрока

например.

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { 
    [player release]; // releases the player object 
}