iOS playing audio in detailViewController from NSDictionary in mainViewController

gbenna

macrumors member
Original poster
Jul 27, 2011
62
0
OK I have a strange one

I have some audio files in my main bundle

audio1.caf
audio2.caf
etc.

I put them into an NSDictionary with objects and keys so that when a certain button is tapped a detailView is loaded and then in that view I have some buttons and AVAudioPlayers which when tapped are to play the audio they are related to.

My problem is that when the first button is tapped the correct audio plays but on other buttons the same audio plays.

I removed the audio1.caf from my main bundle, and from the apps folder on the computer, I disconnected the button from the action in the IB, I commented out the AVAudioPlayer associated with the button and I commented out the path to the file and I deleted the app from my phone and even did a hard restart to reset it.

After all that I loaded the app onto my phone pressed the 2nd button linked to another audio file that does exist in the main bundle and guess what?
The deleted audio played, HOW?
Could someone explain this to me and help me make this work right.

Here is my dictionary in the mainViewController


Code:
if ([vc isKindOfClass:[FinalDetailViewController class]])
    {
        FinalDetailViewController*lcVC =(FinalDetailViewController*)vc;

NSMutableDictionary *myDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                       @"audio1.caf",@"firstAudioKey",
                                       @"audio2.caf",@"secondAudioKey",nil];
    lcVC.myDictionary =myDictionary;   
        }
    [self.navigationController pushViewController:vc animated:YES];
    }
And this is the code in the FinalDetailViewController

Code:
- (void)viewDidLoad
{
    AVAudioSession *session = [AVAudioSession sharedInstance];
    [session setCategory:AVAudioSessionCategoryPlayback error:nil];
    [session setActive:YES error:nil];

    [super viewDidLoad];
   

   NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:self.firstAudioKey ofType:@"caf"]];
    theAudio2 = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
    theAudio2.delegate =self;
    theAudio2.volume = 10.0; 
    theAudio2.numberOfLoops = 0;

   NSURL *url2 = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:self.secondAudioKey ofType:@"caf"]];
    theAudio3 = [[AVAudioPlayer alloc] initWithContentsOfURL:url2 error:nil];
    theAudio3.delegate =self;
    theAudio3.volume = 10.0; 
    theAudio3.numberOfLoops = 0;
}

-(IBAction)buttonPressed:(id)sender  {if ([theAudio2 isPlaying]){[theAudio2 pause]; }else{[theAudio2 play];}}

-(IBAction)buttonPressed2:(id)sender {if ([theAudio3 isPlaying]){[theAudio3 pause]; }else{[theAudio3 play];}}

so I have the audio in the main bundle which is the object for the key in myDictionary.

I start the audio session and set up the path to the audio files and have a separate AVAudioPlayer alloc and init the file and I have separate buttons and IBActions to play the separate files.

Why is the same audio being played on all even when it doesn't exist?

I'm wondering if when I alloc the first player and file it stays in memory and so just keeps playing over and over. But there is no way now to release the player. Do I need separate audio sessions?

HELP
 

dejo

Moderator
Staff member
Sep 2, 2004
15,725
447
The Centennial State
First, before you do anything else, you should avoid using error:nil and actually pass in a NSError parameter. Then you should check what it contains after the call, because if it's not nil, you have an issue. An issue that requires debugging.
 
Last edited:

gbenna

macrumors member
Original poster
Jul 27, 2011
62
0
playing audio in detailViewController from NSDictionary in mainViewController

So I replaced all the nils with NULL.
 

gbenna

macrumors member
Original poster
Jul 27, 2011
62
0
playing audio in detailViewController from NSDictionary in mainViewController

Ok so here's how I've changed the code to look like this.


Code:
-(IBAction)buttonPressed3:(id)sender { 
//so I've added this so I can see where error are, not quite sure how
    NSError *error = nil;
    NSURL *url2 = [NSURL fileURLWithPath:[myDictionary objectForKey:@"spanishAudioKey"]];
    theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:url2 error:&error];
    theAudio.delegate =self;
    theAudio.volume = 10.0; 
    theAudio.numberOfLoops = 0;
    if ([theAudio isPlaying]){[theAudio pause]; }else{[theAudio play];}}
thank you Dejo for your help.
 

gbenna

macrumors member
Original poster
Jul 27, 2011
62
0
playing audio in detailViewController from NSDictionary in mainViewController

So upon doing some more reading and research I have updated my code again

to this


Code:
-(IBAction)buttonPressed2:(id)sender {
    NSError *error = nil;
     NSString *audioName = [myDictionary objectForKey:@"firstAudioKey"];
    NSURL *url = [NSURL fileURLWithPath:audioName];
    theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
    
    theAudio.delegate =self;
    theAudio.volume = 10.0; 
    theAudio.numberOfLoops = 0; 
     NSLog(@"%@",url);
    if ([theAudio isPlaying]){[theAudio pause]; }else{[theAudio play];}
            }
when I tap the button my log shows

2012-03-15 20:26:20.515 my little app[2482:10703] audio1.caf -- file://localhost/

but still no music.
I will continue to look and try.
 

dejo

Moderator
Staff member
Sep 2, 2004
15,725
447
The Centennial State
After you're done calling initWithContentsOfURL:error:, you should check to see if it reported any errors. That's the whole reason for not passing it nil.
 

gbenna

macrumors member
Original poster
Jul 27, 2011
62
0
playing audio in detailViewController from NSDictionary in mainViewController

Dejo,
I tried the following code
Code:
if(error){
NSLog (@"Failed with reason:%@", [error localizedDescription]);
after this code in the detailViewController


Code:
-(IBAction)buttonPressed3:(id)sender { 
   
   
    NSError *error = nil;
  NSURL *url2 = [NSURL fileURLWithPath:[[NSBundle mainBundle]pathForResource:self.firstAudioKey ofType:@"caf"]];
    theAudio3 = [[AVAudioPlayer alloc] initWithContentsOfURL:url2 error:&error];
    
    theAudio3.delegate =self;
    theAudio3.volume = 10.0; 
    theAudio3.numberOfLoops = 0; 
    NSLog (@"%@",url2);
    if( error ){
        NSLog(@"Failed with reason: %@", [error localizedDescription]); 
    }
and then I put a break point after that

This is the response displayed in the all output debug area

2012-03-17 08:08:02.402 my little app[445:707] file://localhost/var/mobile/Applications/8CED118C-893A-4A10-A5E8-3823CD11E063/my%20little%20app.app/audio3.caf

and this is in the local area

self FinalDetailViewController *const 0x0026de40
_cmd SEL 0x000e0643 "buttonPressed3"
*_cmd SEL 0x74747562
sender id 0x00276090
[0] id
error NSError * 0x00000000
NSObject NSObject
isa Class
[0] Class
_reserved void *
_code NSInteger
_domain NSString *
NSObject NSObject
isa Class
[0] Class
_userInfo NSDictionary * key/value pairs
NSObject NSObject
isa Class
[0] Class
url2 NSURL * 0x00269af0 "file://localhost/var/mobile/application/8Cbunch o #and letters/my%20little%20app..."
NSObject NSObject
isa Class 0x3edb5c28
[0] Class
_urlString NSString * 0x03001d80
NSObject NSObject
isa Class 0xf0000000
[0] Class
_baseURL NSURL * 0x802fe029
_clients void * 0x08000100
_reserved void * 0x0028d650

the difference between the two bold parts is that of the end (I think) locally the file audio1.caf is not there and in all output a different audio in the mainBundle is there. If I apply the same code to the other buttons I get the same response with the same audio3.caf being played even though it isn't called. It is not the first audio file in the mainBundle so I don't understand why it is being played. I'm thinking the app is trying to resolve the issue and finds the audio in the cache and plays it.
 
Last edited:

gbenna

macrumors member
Original poster
Jul 27, 2011
62
0
playing audio in detailViewController from NSDictionary in mainViewController

I finally figured this out. It took me a while I know.

Here is my code if anyone wants to look at it and tell me what's wrong.


Code:
-(IBAction)buttonPressed2:(id)sender {
    NSError *error = nil;
    NSString *theAudio = [[NSBundle mainBundle]bundlePath];
    NSString *audioPath = [theAudio stringByAppendingPathComponent:[myDictionary objectForKey:@"firstAudioKey"]];
    NSURL *url = [NSURL fileURLWithPath:audioPath];
    theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
    theAudio.delegate =self;
    theAudio.volume = 10.0; 
    theAudio.numberOfLoops = 0;
    NSLog (@"%@",firstAudioKey);
    if ([theAudio isPlaying]){[theAudio pause]; }else{[theAudio play];}}
Thanks to everyone, especially dejo.
 
Last edited by a moderator:

dejo

Moderator
Staff member
Sep 2, 2004
15,725
447
The Centennial State
For one, you're ignoring the returned NSError again.

For two, you are creating theAudio as an NSString and then assigning it a AVAudioPlayer later. That seem reasonable to you?

For three, "tell me what's wrong". We need to know what's not working first.