点击播放按钮后,我收到内存泄漏....
我正在使用“运行和性能工具”下的“泄漏”工具进行测试....在模拟器上
第一次点击播放按钮时,我发现了泄漏.....
这是我的代码......
-(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;
}
答案 0 :(得分:2)
我认为,以下声明是内存泄漏的来源,
player = [[AVAudioPlayer alloc] initWithContentsOfURL:file error:&err];
以下是讨论同一问题的SO帖子。
AVAudioPlayer Memory Leak - Media Player Framework
这是博客文章
<强>编辑:强>
根据博客教程,您的代码必须如下所示。
-(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 :(得分:1)
Jhaliya的回答中的博客文章描述了一种泄漏,这种泄漏特定于当你的播放器无法启动音频时的情况,例如当它找不到文件时。
您的代码存在的真正问题是,只有在用户明确停止播放音频时才会释放播放器。如果音频播放到最后,您有一个keepCount为1的播放器实例。然后,如果用户再次播放,则创建一个新播放器并将其分配给player
变量,泄漏旧变量。
最简单的解决方案是使player
成为保留属性:
@property(nonatomic,retain)AVAudioPlayer *player;
然后,不是直接分配到ivar,而是使用mutator来设置播放器,如果有的话,它将隐式释放先前设置的实例:
[self setPlayer:[[[AVAudioPlayer alloc] initWithContentsOfURL:file error:&err] autorelease];
不要忘记在你的dealloc中发布它:
-(void)dealloc {
[player release];
[super dealloc];
}