我遇到了与AVAudioPlayer相关的一些奇怪的内存泄漏问题,在尝试了所有想到的内容后我需要帮助。
以下是问题的简短描述 - 代码紧随其后。 我初始化我的播放器并开始在无限循环播放音轨(无限循环或一次播放没有改变问题)。 在音乐开始几秒后,我切换到另一个音轨,因此我创建了一个新的播放器,初始化它,释放旧的播放器(正在播放)然后将新的播放器设置到位并播放它。
在那个时间点(在我调用新播放器之后 - [播放器播放])我得到内存泄漏(3.5Kb)。
我尝试了以下内容:
停止旧播放器,然后释放它 - 无效
播放指令后立即释放播放器 - 未开始播放
发布两次旧播放器 - 崩溃
当我创建并播放第一个播放器时,内存泄漏不会发生!
另外,在参考文献中它确实说'play'是异步的,所以它可能会将ref计数增加1,但在这种情况下,为什么没有[Player stop]帮助?
谢谢,
以下是有关我如何使用它的代码的一些部分:
- (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 :(得分: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 :(得分:2)
实施协议AVAudioPlayerDelegate及其方法audioPlayerDidFinishPlaying:成功:然后释放音频播放器对象
例如
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
[player release]; // releases the player object
}
答案 2 :(得分: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对象。仪器应该能够为您验证这一点。
答案 3 :(得分:-2)
尝试将MediaPlayer.framework添加到您的项目中