Reputation: 1819
I am trying to play a click sound on every button click in my app For that i created a Utility class whose .h and .m is as follows
.h file
@interface SoundPlayUtil : NSObject<AVAudioPlayerDelegate,AVAudioSessionDelegate>
{
AVAudioPlayer *audioplayer;
}
@property (retain, nonatomic) AVAudioPlayer *audioplayer;
-(id)initWithDefaultClickSoundName;
-(void)playIfSoundisEnabled;
@end
.m file
@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
and on button click on any class i am doing
SoundPlayUtil *obj = [[SoundPlayUtil alloc] initWithDefaultClickSoundName];
[obj playIfSoundisEnabled];
[obj release];
Its working fine and i succeeded to play sound. Problem arises when i analysed the code. Compiler shows that there is memory leak in initWithDefaultClickSoundName method in .m of utility class as i am sending alloc method to self.audioplayer and not releasing it.
What is the best place of releasing this object?
Upvotes: 5
Views: 324
Reputation: 119282
self.audioplayer =[[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:BS_path_blue] error:NULL];
Here, you create a new object, then assign it to a retained property. However, apart from the property, you have no reference to the object again, so it leaks. You've increased the retain count twice.
To fix, in order of preference:
Create a local variable, assign it to the property, then release it.
Object *object = [[Object alloc] init];
self.property = object;
[object release];
Add a autorelease call to the object as you are adding it: self.property = [[[Object alloc] init] autorelease];
Upvotes: 0
Reputation: 107221
The issue is when you alloc the object it's retainCount will be 1, you are assigning that object to a retain property object. Then it'll again retain the object hence the retainCount will be 2.
The setter code of a retain property is something like:
- (void)setAudioplayer: (id)newValue
{
if (audioplayer != newValue)
{
[audioplayer release];
audioplayer = newValue;
[audioplayer retain];
}
}
Change the :
self.audioplayer =[[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:BS_path_blue] error:NULL];
like;
self.audioplayer =[[[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:BS_path_blue] error:NULL] autorelease];
or like:
AVAudioPlayer *player = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:BS_path_blue] error:NULL];
self.audioplayer = player;
[player release];
Upvotes: 2