2012-12-19 28 views
5

我想在我的应用程序 发挥每按一下按钮点击声音,当我创建的,其h和.M如下内存泄漏维持性

.h文件中的实用程序类

@interface SoundPlayUtil : NSObject<AVAudioPlayerDelegate,AVAudioSessionDelegate> 
{ 
    AVAudioPlayer *audioplayer; 
} 
@property (retain, nonatomic) AVAudioPlayer *audioplayer; 
-(id)initWithDefaultClickSoundName; 
-(void)playIfSoundisEnabled; 
@end 

.m文件

@implementation SoundPlayUtil 
@synthesize audioplayer; 

-(id)initWithDefaultClickSoundName 
{ 
self = [super init]; 
    if (self) 
{ 
    NSString* BS_path_blue=[[NSBundle mainBundle]pathForResource:@"click" ofType:@"mp3"]; 
    self.audioplayer =[[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:BS_path_blue] error:NULL]; 
    [self.audioplayer prepareToPlay]; 
} 
return self; 
} 

-(void)playIfSoundisEnabled 
{ 
if ([[NSUserDefaults standardUserDefaults] boolForKey:soundStatus]==YES) 
{ 
    [self.audioplayer play]; 
} 
} 

-(void)dealloc 
{ 
[audioplayer release]; 
[super dealloc]; 
} 
@end 

,并在任何类别按钮点击我做

SoundPlayUtil *obj = [[SoundPlayUtil alloc] initWithDefaultClickSoundName]; 
[obj playIfSoundisEnabled]; 
[obj release]; 

它的工作正常,我成功播放声音。当我分析代码时出现问题。 编译器显示内存泄漏initWithDefaultClickSoundName实用程序类的.m中的方法,因为我将alloc方法发送到self.audioplayer并且未释放它。

发布此对象的最佳地点是什么?

+0

是否使用ARC? –

+0

不,没有使用ARC –

回答

2

问题是当你分配对象的retainCount将是1时,你将该对象分配给一个retain属性对象。然后,它会再次保留对象因此retainCount将2.

一个保留setter方法的代码是一样的东西:

- (void)setAudioplayer: (id)newValue 
{ 
    if (audioplayer != newValue) 
    { 
     [audioplayer release]; 
     audioplayer = newValue; 
     [audioplayer retain]; 
    } 
} 

更改:

self.audioplayer =[[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:BS_path_blue] error:NULL]; 

等;

self.audioplayer =[[[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:BS_path_blue] error:NULL] autorelease]; 

或类似:

AVAudioPlayer *player = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:BS_path_blue] error:NULL]; 
self.audioplayer = player; 
[player release]; 
+0

感谢您的快速回答,我试图避免autorelease,所以如果我实现第二个选项,你给。在这种情况下,因为我保留** self.audioplayer **并保留audioplayer对象的数量是1.现在我将它分配给新的对象** player **,其保留数也是1.是否会出现这种情况在将新值赋给** self.audioplayer **之后,我放弃了保留计数为1的对象的引用。 –

+0

之后,我释放临时对象。所以它不会造成任何孤儿或造成泄漏 –

+0

为什么要避免autorelease?无论如何,一个声音对象几乎可以保证比一次遍历运行循环的时间更长,自动释放与播放声音的代价可以忽略不计。请注意,保留计数可能是1,也可能不是1。绝对保留数是毫无意义的。 – bbum

0
self.audioplayer =[[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:BS_path_blue] error:NULL]; 

在这里,你创建一个新的对象,然后将其分配到保留的财产。但是,除了这个属性之外,你再也没有引用该对象,所以它会泄漏。你已经增加了两次保留计数。

要修复,按优先顺序:

  1. 转换为弧;)
  2. 创建一个局部变量,它分配给属性,然后松开。

    Object *object = [[Object alloc] init]; 
    self.property = object; 
    [object release]; 
    
  3. 添加一个自动释放调用对象要添加它:self.property = [[[Object alloc] init] autorelease];