2009-08-29 7 views
6

私はAVAudioPlayerに関連した奇妙なメモリリークの問題に悩まされています。AVAudioPlayerメモリリーク

問題の簡単な説明は次のとおりです。コードはすぐ後に表示されます。 私はプレイヤーを初期化し、無限ループでサウンドトラックを再生します(無限ループまたは一回の再生でも問題は変わりません)。 音楽が始まって数秒後に別のサウンドトラックに切り替えるので、新しいプレーヤーを作成して初期化し、再生中の古いものをリリースして、新しいものをリリースして再生します。

その時点(私は新しいプレーヤー - [Player play]を呼び出した直後)に、メモリリーク(3.5Kb)が発生します。

は、私が試した次

  • が古いプレーヤーを停止していないし、それを解放 - プレーヤーは、右のプレイ命令の後には何の影響

  • リリース - 再生を開始しませんでしたが

  • 古いプレーヤーを2回リリース - クラッシュ

  • 作成して再生するとメモリリークは起こりません最初の選手!

また、参照して、それは「遊び」は非同期であるので、おそらくそれが1で参照カウントを増加させることを言うんが、この場合には、理由[プレーヤーを停止]助けにはなりませんでしたか?

おかげで、ここで

が、私はそれを使用する方法については、コードの一部です:

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

あなたのコードは、私が見た限り私には似ています。だから、おそらく問題の原因となっているコードがあります。

私はあなたが一種の奇妙なイディオムを使用していると言います。彼らは実際にそれを容易に可能性のある、あなたのsetAudioPlayer方法に来るとき、あなたが唯一の「プレーヤー」のオブジェクトを保持して、このように

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

:むしろ作成に保持し、セットに解放するよりも、私はこのような何かをしたいです追跡する。

また、実際に漏れているAVAudioPlayerオブジェクトであることを確認してください。インストゥルメントはこれをあなたに確認できるはずです。

+0

ありがとうございました。 はい - InstrumentsでAVAudioPlayerであることを確認しました。 方法について - 私は実際に別のトラックを保存し、名前を一致させたり、同じトラックを何度もダウンロードする代わりに、再生していない場合に再利用したりするため、これを使用します。 「Alloc」を実行した後に呼び出し元からPlayerが取得されていることを知っているので、それが既に保持されていることが分かります(間違っていない限り)。 – Adi

7

ここでは、メモリリークを起こさずにAVAudioPlayerを作成する方法を示します。 See this page for explaination

私のアプリでAVAudioPlayerのリークが100%削除されたことを確認しました。プロジェクトに

+1

NSData * audioData行... – SpaceDog

+0

このコードは本当に奇妙で、alloc vs init呼び出しを分割する理由はありません。より良い一般的なアプローチについては、http://stackoverflow.com/questions/17603551/arc-forbids-autorelease/17604365#17604365を参照するか、[[[AVAudioPlayer alloc] initWithData:audioData error:NULL]のようにautoreleaseを追加するだけです。autorelease ] – MoDJ

-2

てみプロトコルAVAudioPlayerDelegateとそのメソッドを実装しaudioPlayerDidFinishPlaying:首尾:その後、

例えばオーディオプレーヤオブジェクトを解放します。

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

'MediaPlayer.framework'? 'AVAudioPlayer'は' AVFoundation.framework'にあり、 'MediaPlayer'は必要ありません。詳しく教える? –

2

をMediaPlayer.frameworkを追加

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