2012-12-19 49 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];