Aaron Chapman Aaron Chapman - 2 months ago 5
iOS Question

Stop AVAudioPlayer in another class

I've searched multiple forums including this one, and cannot find a solution to my problem. I have a sound file set to play when my "IQTest" view controller loads. It plays fine, and I can stop the sound in "IQTest" view controller.


@interface IQTest : UIViewController
AVAudioPlayer *theAudio;
@property (nonatomic, strong) AVAudioPlayer *theAudio;


- (void)viewDidLoad
[super viewDidLoad];

NSString *path = [[NSBundle mainBundle] pathForResource:@"IQTestBackgroundMusic" ofType:@"mp3"];
AVAudioPlayer* soundTrack=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
soundTrack.numberOfLoops = -1;
self.theAudio = soundTrack;
[theAudio play];

I want to stop playing the sound when a user presses the button in "IQTestQuestionThree"'s view controller, but when I try at stop the sound, it either keeps playing, or my app crashes. I've tried multiple ways, and have yet to find one to stop my sound.


- (IBAction) question3Answer1
IQTest *IQTestAudio = [[IQTest alloc] init];
[IQTestAudio.theAudio stop];

iqScaryFace.hidden = NO;
homeButton.hidden = NO;
homeButtonLabel.hidden = NO;
answer1Button.hidden = YES;
answer2Button.hidden = YES;
answer3Button.hidden = YES;
answer4Button.hidden = YES;

Thank you for any help I can get.

- (IBAction) question3Answer1
    IQTest *IQTestAudio = [[IQTest alloc] init];
    [IQTestAudio.theAudio stop];

This code creates a brand new IQTest object (which is a UIViewController subclass -- and therefore has a confusing name), and then calls its stop method.

This brand-new IQTest object (maybe rename it IQTestViewController?) was just created -- it isn't the same object that started playing the sound. So you're expecting it to stop playing something it has no control over. (At least, I don't expect it to work, without seeing more code.)

I want to stop playing the sound when a user presses the button in "IQTestQuestionThree"'s view controller

How is the view hierarchy structured?

Is IQTestQuestionThree a view controller whose parent is IQTest? (Again, consider renaming IQTestQuestionThree to something like IQTestQuestionThreeViewController.) If so, you could use the delegate pattern to have IQTestQuestionThree alert IQTest to stop playing the sound.

If your view controller hierarchy is more complex, and/or if there are other view controllers in other places that might want to stop playing the sound, consider creating a model class for sound playing to act as a proxy for playing sounds, instantiate that model class in your app delegate, and pass it along to all the view controllers that need to control audio.

(UIViewController subclasses, by convention, have "ViewController" as a suffix on their name. You'll find this is the case in Apple's source code. If you want to write your code for readability, you should follow conventions for what language in which you're writing as closely as possible.)