elce
elce

Reputation: 312

Using AVAudioPlayer from class outside ViewController not working

New to iOS and Objective-C, have been struggling to figure this out. I have a class that holds a strong reference to an AVAudioPlayer object and defines a method to play an mp3 depending on the parameter 'tag', which belongs to a UIButton. In my view controller I have a method that uses this class to play a sound when a button is pressed. But when I run the simulator and press the button, the mp3 is not being played. When I don't use the other class and make the AVAudioPlayer belong to my ViewController, initialize it in viewDidLoad, and call play right in the IBAction method, it works fine. I checked that the files are available to my project and that they are being referenced correctly in the code.

I looked around and found this and this, neither solved my problem. Here's my code

GuitarTuner.h

#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>

@interface GuitarTuner : NSObject
- (void) play: (NSUInteger)tag;
@end

GuitarTuner.m

#import "GuitarTuner.h"
#import <AVFoundation/AVFoundation.h>

@interface GuitarTuner()
@property (strong, nonatomic) AVAudioPlayer *audioPlayer;
@end

@implementation GuitarTuner

- (void) play:(NSUInteger)tag
{
    NSString *note;
    switch (tag) {
        case 0:
            note = @"Low-E";
            break;
        case 1:
            note = @"A";
            break;
        case 2:
            note = @"D";
            break;
        case 3:
            note = @"G";
            break;
        case 4:
            note = @"B";
            break;
        case 5:
            note = @"Hi-E";
            break;
    }

    NSString *path = [[NSBundle mainBundle] pathForResource:note ofType:@"mp3"];
    NSURL *soundURL = [NSURL fileURLWithPath:path];
    self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundURL error:nil];
    [self.audioPlayer play];
}

@end

ViewController.m

#import "ViewController.h"
#import "GuitarTuner.h"

@interface ViewController ()
@property (strong, nonatomic) GuitarTuner *tuner;
@end

@implementation ViewController

- (GuitarTuner *) tuner
{
    if (!_tuner) return [[GuitarTuner alloc] init];
    return _tuner;
}

- (IBAction)noteButton:(id)sender
{
    UIButton *button = (UIButton*)sender;
    [self.tuner play:button.tag];
}


@end

Thanks in advance

EDIT:

Silly mistake! Just didn't properly initialize GuitarTuner property in the getter in ViewController -- should be _tuner = [[GuitarTuner alloc] init] Answer below works too.

Upvotes: 1

Views: 189

Answers (1)

Silviu St
Silviu St

Reputation: 1842

Try to initialise AVAudioPlayer like this

NSError *error;
self.audioPlayer = [[AVAudioPlayer alloc]
                     initWithContentsOfURL:[[NSBundle mainBundle] URLForResource:note withExtension:@"mp3"] error:&error];

UPDATE:

You give yourself your answer:

When I don't use the other class and make the AVAudioPlayer belong to my ViewController, initialize it in viewDidLoad, and call play right in the IBAction method, it works fine.

Try to alloc tuner in viewDidLoad or create from your class GuitarTuner a singleton and from there everything will be much easier.

Also comment this:

- (GuitarTuner *) tuner
{
    if (!_tuner) return [[GuitarTuner alloc] init];
    return _tuner;
}

Upvotes: 1

Related Questions