Daniel Tovesson
Daniel Tovesson

Reputation: 2590

AVAudioPlayer in class category with ARC

I'm trying to add a custom click sound on all my buttons in my application. I've created a class category for UIButton with the following code in it:

NSURL *soundURL = [NSURL fileURLWithPath:[[NSBundle bundleWithIdentifier:@"com.apple.UIKit"] pathForResource:@"Tock" ofType:@"aiff"]];
NSError *error;

AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundURL error:&error];

if(audioPlayer == nil){
    NSLog(@"%@", [error description]);
} else{
    [audioPlayer play];
}

All this is executed in: - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

But from what I understand there is a common problem with ARC (wich I am using) here. The audioPlayer objects seems to be released before the sound is played. I've also had a look at AudioServicesPlaySystemSound();. But that's no alternative for me at the moment because I need a volume level controller in my application and I've found no way to change the system volume without leaving the app.

My question is: Is there any way to make a strong reference to my audioPlayer object in the UIButton class category? Or is there any other, maybe better way, to get this working?

Upvotes: 1

Views: 168

Answers (1)

Carl Veazey
Carl Veazey

Reputation: 18363

When adding any object relationship in a category, it's always worth looking at associated objects. Use the objc_setAssociatedObject() and objc_getAssociatedObject() functions. Make sure to use a unique pointer value for the key, and in your case you'll definitely want to use one of the retain association policies to ensure your object's lifespan is appropriate.

Upvotes: 2

Related Questions