2011-11-23 6 views
7

Ho creato un'app con tab bar,nav bar and table view.Riproduzione audio con controlli in iOS

Nella visualizzazione tabella è possibile scegliere di ascoltare un po 'di audio.

Nuova vista si apre e lì ho alcuni controlli come: play, pausa, cursore del volume, cursore di avanzamento, etichetta con l'ora corrente.

Funziona, ma non perfetto. Posso riprodurre l'audio, posso mettere in pausa l'audio, posso anche usare il cursore per saltare avanti o indietro. Ma ora:

Quando premo il pulsante Indietro sulla barra di navigazione, la canzone continua a essere riprodotta. Va bene, ma quando torno di nuovo alla vista, il timer e il cursore si resettano. Non riesco a mettere in pausa la canzone, ho solo bisogno di aspettare che smetta di suonare.

Inoltre, quando ho colpito il gioco, tornare alla visualizzazione della tabella, scegliere un altro file di giocare, il primo file non smettere di giocare.

ecco il codice Audio1DetailViewController.h:

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

    @interface Audio1DetailViewController: UIViewController <AVAudioPlayerDelegate> { 

    IBOutlet UISlider *volumeControl; 
    IBOutlet UILabel *timerLabel; 
    IBOutlet UISlider *progressBar; 

    AVAudioPlayer *audioPlayer; 
    NSTimer *playbackTimer; 

    } 

    @property (nonatomic, retain) IBOutlet UISlider *volumeControl; 
    @property (nonatomic, retain) IBOutlet UILabel *timerLabel; 
    @property (nonatomic, retain) IBOutlet UISlider *progressBar; 
    @property (nonatomic, retain) NSTimer *playbackTimer; 
    @property (nonatomic, retain) AVAudioPlayer *audioPlayer; 
    -(IBAction) playAudio; 
    -(IBAction) stopAudio; 
    -(IBAction) adjustVolume; 
    -(IBAction) sliderChanged; 

    @end 

ecco il codice Audio1DetailViewController.m:

 #import "Audio1DetailViewController.h" 


    @implementation Audio1DetailViewController 

    @synthesize volumeControl, timerLabel, playbackTimer, progressBar, audioPlayer; 

    -(void)playAudio 
    { 
    playbackTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 
    target:self 
    selector:@selector(updateTime) 
    userInfo:nil 
    repeats:YES]; 
    [audioPlayer play]; 
    } 
    -(void)stopAudio 
    { 
    [playbackTimer invalidate]; 
    [audioPlayer stop]; 
    } 
    -(void)adjustVolume 
    { 
    if (audioPlayer != nil) 
    { 
    audioPlayer.volume = volumeControl.value; 
    } 
    } 

    -(void)updateTime 
    { 
    float minutes = floor(audioPlayer.currentTime/60); 
    float seconds = audioPlayer.currentTime - (minutes * 60); 

    float duration_minutes = floor(audioPlayer.duration/60); 
    float duration_seconds = 
    audioPlayer.duration - (duration_minutes * 60); 

    NSString *timeInfoString = [[NSString alloc] 
    initWithFormat:@"%0.0f.%0.0f/%0.0f.%0.0f", 
    minutes, seconds, 
    duration_minutes, duration_seconds]; 

    timerLabel.text = timeInfoString; 
    [timeInfoString release]; 
    } 

    - (void)viewDidLoad { 
    [super viewDidLoad]; 
    NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] 
    pathForResource:@"001Fatiha" 
    ofType:@"MP3"]]; 

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

    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil]; 
    [[AVAudioSession sharedInstance] setActive: YES error: nil]; 

    if (error) 
    { 
    NSLog(@"Error in audioPlayer: %@", 
    [error localizedDescription]); 
    } else { 
    audioPlayer.delegate = self; 
    [audioPlayer prepareToPlay]; 
    } 


    playbackTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self 
    selector:@selector(updateSlider) userInfo:nil repeats:YES]; 

    progressBar.maximumValue = audioPlayer.duration; 
    // Set the valueChanged target 
    [progressBar addTarget:self action:@selector(sliderChanged:) forControlEvents: 
    UIControl EventValueChanged]; 
    } 

    - (void)updateSlider { 
    // Update the slider about the music time 
    progressBar.value = audioPlayer.currentTime; 
    } 

    - (IBAction)sliderChanged:(UISlider *)sender { 
    // Fast skip the music when user scroll the UISlider 
    [audioPlayer stop]; 
    [audioPlayer setCurrentTime:progressBar.value]; 
    [audioPlayer prepareToPlay]; 
    [audioPlayer play]; 
    } 

    -(void)audioPlayerDidFinishPlaying: 
    (AVAudioPlayer *)player successfully:(BOOL)flag 
    { 
    } 


    -(void)audioPlayerDecodeErrorDidOccur: 
    (AVAudioPlayer *)player error:(NSError *)error 
    { 
    } 
    -(void)audioPlayerBeginInterruption:(AVAudioPlayer *)player 
    { 
    } 
    -(void)audioPlayerEndInterruption:(AVAudioPlayer *)player 
    { 
    } 

    -(void)viewDidUnload { 
    audioPlayer = nil; 
    volumeControl = nil; 

    } 

    -(void)dealloc { 
    [audioPlayer release]; 
    [volumeControl release]; 
    [playbackTimer release]; 
    [super dealloc]; 
    } 

    @end 

Ecco l'AudioTableViewController.h

 #import <UIKit/UIKit.h> 

    @class Audio1DetailViewController; 


    @interface AudioTableViewController : UITableViewController 
    <UITableViewDelegate,UITableViewDataSource>{ 


    IBOutlet UITableView *audioTableView; 
    NSMutableArray *audioArray; 
    Audio1DetailViewController *audio1DetailViewController;   
    } 

    @property (nonatomic, retain) NSMutableArray *audioArray; 
    @property (nonatomic, retain) Audio1DetailViewController *audio1DetailViewController; 

    @end 

E l'AudioTableViewController .m

#import "AudioTableViewController.h" 
    #import "Audio1DetailViewController.h" 

    #import "DEQAppDelegate.h" 

    @implementation AudioTableViewController 
    @synthesize audioArray; 
    @synthesize audio1DetailViewController; 

    - (id)initWithStyle:(UITableViewStyle)style 
    { 
     self = [super initWithStyle:style]; 
     if (self) { 
      // Custom initialization 
    { 
     return self; 
    } 

    - (void)didReceiveMemoryWarning 
    { 
     // Releases the view if it doesn't have a superview. 
     [super didReceiveMemoryWarning]; 

     // Release any cached data, images, etc that aren't in use. 
    } 

    #pragma mark - View lifecycle 

    - (void)viewDidLoad{ 
     [super viewDidLoad]; 
     self.title = NSLocalizedString(@"Audio", @"Audio"); 
     self.audioArray = [[NSArray alloc] initWithObjects: 
          @"1. Het Begin", @"2. De Mensen", //etcetera      
        nil]; 
     // Uncomment the following line to preserve selection between presentations. 
     self.clearsSelectionOnViewWillAppear = NO; 

     // Uncomment the following line to display an Edit button in the navigation bar for this 
     view controller. 
     // self.navigationItem.rightBarButtonItem = self.editButtonItem; 
    } 

    - (void)viewDidUnload 
    { 
     [super viewDidUnload]; 
     // Release any retained subviews of the main view. 
     self.audioArray = nil; 
    } 

    - (void)viewWillAppear:(BOOL)animated 
    { 
     [super viewWillAppear:animated]; 
    } 

    - (void)viewDidAppear:(BOOL)animated 
    { 
     [super viewDidAppear:animated]; 
    } 

    - (void)viewWillDisappear:(BOOL)animated 
    { 
     [super viewWillDisappear:animated]; 
    } 

    - (void)viewDidDisappear:(BOOL)animated 
    { 
     [super viewDidDisappear:animated]; 
    } 

    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
    { 
     // Return YES for supported orientations 
     return (interfaceOrientation == UIInterfaceOrientationPortrait); 
    } 

    #pragma mark - Table view data source 

    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
    { 
    #warning Potentially incomplete method implementation. 
     // Return the number of sections. 
     return 1; 
    } 

    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
    { 
    #warning Incomplete method implementation. 
     // Return the number of rows in the section. 
     return [self.audioArray count]; 
    } 

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: 
     (NSIndexPath *)indexPath 
    { 
     static NSString *CellIdentifier = @"Cell"; 

     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
     if (cell == nil) { 
      cell = [[[UITableViewCell alloc] initWithStyle: 
     UITableViewCellStyleDefaultreuseIdentifier:CellIdentifier] autorelease]; 
     } 

     // Configure the cell... 
     cell.textLabel.text = [self.audioArray objectAtIndex:[indexPath row]]; 

     return cell; 
    } 

    #pragma mark - Table view delegate 

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
    { 
     // Navigation logic may go here. Create and push another view controller. 

     NSUInteger row = indexPath.row; 

     if (row == 0) 
     { 
    Audio1DetailViewController *audio1DetailViewController =[[Audio1DetailViewController alloc] 
    initWithNibName:@"Audio1DetailViewController" bundle:nil]; 
    audio1DetailViewController.title = @"Audio"; 
    [self.navigationController pushViewController:audio1DetailViewController animated:YES]; 
    [audio1DetailViewController release]; 

     } 

     if (row == 1) 
     { 
      //etcetera 
     } 

    } 
    - (void)dealloc{ 
     [audioArray release]; 
     [super dealloc]; 
    } 

    @end 
+0

, anche [Vedere di Apple doc.] (Http://developer.apple.com/library/ios/#documentation/mediaplayer/reference/MPMusicPlayerController_ClassReference/Reference/Reference.html) – HDdeveloper

risposta

9

Suggerisco di creare un oggetto giocatore globale. Perché in questo momento, ogni volta che si preme questa vista sul controller di navigazione, ne viene creata una nuova. Questo significa anche che non hai alcun riferimento al giocatore precedente (e non puoi fermarlo). Quindi: dichiarare AVAudioPlayer un gradino più in alto (nella vista tabella). Ora, quando selezioni una riga, assegnala a una proprietà di questa nuova vista (quella che hai collegato).

Lavori con lo storyboard? Quindi devi implementare il metodo prepareForSegue:. Dare ai tuoi passi sullo storyboard un identificatore (come showPlayer e verificarlo con if (segue.identifier isEqualToString:@"showPlayer")).

Ora nel tuo viewDidLoad fare un controllo se audioPlayer è nullo. Se si

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    if (audioPlayer == nil) 
    { 
     // your init (audioplayer =[[AVAudioPlayer ... 
    } 
    else 
    { 
     if (audioPlayer.isPlaying) 
     { 
      // i.e. pause the player or do other stuff 
     } 
    } 
} 

Spero che questo ti aiuti.

: non pubblicare immagini di codice. Inserisci il codice nella tua risposta o pubblicalo su un sito come pastebin.com e collega quella pagina nella tua domanda. Ciò semplifica la risposta degli altri e suggerisce come modificare il codice.

In risposta al tuo commento: La roba rilevante dovrebbe essere: In AudioTableViewController.h:

@property (strong, nonatomic) AVAudioPlayer *audioPlayer; 

In AudioTableViewController.m:

@synthesize audioPlayer; 
... 
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    // Navigation logic may go here. Create and push another view controller. 

    NSUInteger row = indexPath.row; 

    if (row == 0) 
    { 
     self.audio1DetailViewController =[[Audio1DetailViewController alloc] initWithNibName:@"Audio1DetailViewController" bundle:nil]; 
     self.audio1DetailViewController.title = @"Audio"; 
     self.audio1DetailViewController.audioPlayer = self.audioPlayer; 
     [self.navigationController pushViewController:self.audio1DetailViewController animated:YES]; 
     [self.audio1DetailViewController release]; 
     ... 

Audio1DetailViewController.m

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"001Fatiha" ofType:@"MP3"]]; 

    NSError *error; 

    // this is the important part: if we already have something playing, stop it! 
    if (audioPlayer != nil) 
    { 
     [audioPlayer stop]; 
    } 
    // everything else should happen as normal. 
    audioPlayer = [[AVAudioPlayer alloc] 
       initWithContentsOfURL:url 
       error:&error]; 

    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil]; 
    [[AVAudioSession sharedInstance] setActive: YES error: nil]; 
+0

Hey @ pxldlx, tnx per la risposta. Ho provato ma ho fallito. Sembra semplice quello che hai detto, e ha senso. Ma io non capisco, penso. ho dichiarato l'AVAudioPlayer nel AudioTableViewController.h dal Audio1DetailViewController.h Poi ho spostato tutto il codice (non la parte viewDidLoad) dal Audio1DetailViewController.m a AudioTableViewController.m Ho cambiato anche il File'sOwner in il file xib. Posso riprodurre il brano, ma non premendo il pulsante di riproduzione, ma spostando il cursore di avanzamento. Ho provato alcune altre cose ma dopo 2 giorni, ho rinunciato e ha annullato tutte le modifiche. – iHilas

+0

@iHilas Mh, ok. Senza guardare il tuo codice, non posso davvero aiutarti molto. Puoi modificare la tua domanda originale e aggiungere del codice (principalmente quel codice che hai già postato come immagine ma questa volta come testo per favore :)). Oh e una cosa: non penso che tu debba cambiare così tanto. Tutto rimane uguale, ma si modifica il "proprietario" di audioPlayer in tale superview (nel senso che questo controller ha una proprietà strong). Quando si attraversa il nuovo controller, si passa il riferimento audioPlayer al nuovo controller. –

+0

Ho aggiunto il codice – iHilas

1

Sorprendentemente il MPMoviePlayerController gioca anche un lettore MP3 con comandi !!!

self.moviePlayer=[[MPMoviePlayerController alloc] initWithContentURL:url]; 
[self.moviePlayer.view setFrame:CGRectMake(0, 0, self.videoContainer.bounds.size.width, self.videoContainer.bounds.size.height)]; 
self.moviePlayer.controlStyle=MPMovieControlStyleDefault; 
[self.videoContainer addSubview:self.moviePlayer.view]; 
[self.moviePlayer prepareToPlay]; 
[self.moviePlayer play]; 
+0

Questo è il modo corretto e più diretto per gestire la riproduzione con i controlli. In iOS 8, Apple ha aggiunto ancora più flessibilità a quali controlli mostri (airplay, ecc.) –