playing audio in detailViewController from NSDictionary in mainViewController

Discussion in 'iOS Programming' started by gbenna, Mar 15, 2012.

  1. gbenna macrumors member

    Joined:
    Jul 27, 2011
    #1
    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
     
  2. dejo, Mar 15, 2012
    Last edited: Mar 15, 2012

    dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #2
    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.
     
  3. gbenna thread starter macrumors member

    Joined:
    Jul 27, 2011
    #3
    playing audio in detailViewController from NSDictionary in mainViewController

    So I replaced all the nils with NULL.
     
  4. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #4
    Which makes no difference. Sorry.

    Now would be a good time to find out more about NSError and how to properly use it in your coding.

    Try this:
    Error Handling Programming Guide

    And perhaps this as well:
    Using NSError Explained
     
  5. gbenna thread starter macrumors member

    Joined:
    Jul 27, 2011
    #5
    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.
     
  6. gbenna thread starter macrumors member

    Joined:
    Jul 27, 2011
    #6
    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.
     
  7. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #7
    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.
     
  8. gbenna, Mar 16, 2012
    Last edited: Mar 17, 2012

    gbenna thread starter macrumors member

    Joined:
    Jul 27, 2011
    #8
    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.
     
  9. gbenna, Mar 21, 2012
    Last edited by a moderator: Mar 21, 2012

    gbenna thread starter macrumors member

    Joined:
    Jul 27, 2011
    #9
    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.
     
  10. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #10
    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.
     

Share This Page