Проблема MemoryLeak в следующем случае - PullRequest
1 голос
/ 29 апреля 2011

Я получаю утечку памяти при нажатии кнопки воспроизведения ....

Я тестирую с помощью этого инструмента "Утечка" в разделе "Инструмент запуска и производительности" .... на симуляторе

Я получаю эту утечку при первом нажатии кнопки воспроизведения .....

Вот мой код ....

-(IBAction)play
{


    [self setPlayer];
    [self playme];  
}



-(IBAction)stop
{
    [self stopme];
    [self releasePlayer];

}


-(void)setPlayer
{

    NSURL *file = [[NSURL alloc] initFileURLWithPath:
                   [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"shut up.mp3"]];
    NSError *err = nil;
    player = [[AVAudioPlayer alloc] initWithContentsOfURL:file error:&err];

    [file release];
    player.numberOfLoops = -1;
    [player prepareToPlay];
    player.volume=1.0;


}


-(void)playme
{
    if (!isPlaying)
    {
        [player play];
        isPlaying=YES;
    }
}


-(void)stopme
{
    if (isPlaying)
    {
        [player stop];
        isPlaying=NO;
    }
}

-(void)releasePlayer
{
    if(!isPlaying)
    {
        [player release];
        player=nil;
    }
    isPlaying=NO;
}

Ответы [ 2 ]

2 голосов
/ 29 апреля 2011

Я думаю, что следующее утверждение является источником утечки памяти,

player = [[AVAudioPlayer alloc] initWithContentsOfURL:file error:&err];

Вот SO сообщения, которые обсуждали ту же проблему.

Утечка памяти в AVAudioPlayer

Утечка памяти в AVAudioPlayer

Утечка памяти в AVAudioPlayer - Media Player Framework

Вот пост в блоге

Утечка памяти в AVAudioPlayer

РЕДАКТИРОВАНИЕ:

Согласно руководству по блогу ваш код должен выглядеть следующим образом.

-(void)setPlayer
{

    NSURL *file = [[NSURL alloc] initFileURLWithPath:
                   [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"shut up.mp3"]];
    NSError *err = nil;

    NSData *data = [NSData dataWithContentsOfFile:file];
    AVAudioPlayer *player = [AVAudioPlayer alloc];    
    if([player initWithData:audioData error:NULL])
     {

        player.numberOfLoops = -1;
        [player prepareToPlay];
        player.volume=1.0;
        [player autorelease];
    } 
    else 
    {
        [player release];
        player = nil;
    }
    [file release];
}

В версии без утечек хранится указатель, возвращаемый alloc, а не указатель, возвращаемый initWithData: error :. Таким образом, что бы ни случилось, игрок все еще может быть освобожден.

1 голос
/ 30 апреля 2011

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

Реальная проблема с вашим кодом состоит в том, что вы отпускаете проигрыватель только в том случае, если пользователь явно останавливает звук.Если звук воспроизводится до конца, у вас есть экземпляр проигрывателя с retainCount, равным 1. Затем, если пользователь нажимает кнопку воспроизведения снова, вы создаете нового проигрывателя и назначаете его переменной player, пропуская старую.

Самое простое решение для этого - сделать player сохраненным свойством:

@property(nonatomic,retain)AVAudioPlayer *player;

Затем, вместо того, чтобы назначать ивару напрямую, используйте мутатор для установки игрока, который неявно освободитранее установленный экземпляр, если он есть:

[self setPlayer:[[[AVAudioPlayer alloc] initWithContentsOfURL:file error:&err] autorelease];

И не забудьте освободить его в свой сделке:

-(void)dealloc {
    [player release];
    [super dealloc];
}
...