2011-11-23 25 views
7

Zrobiłem aplikację z tab bar,nav bar and table view.Odtwarzanie dźwięku za pomocą formantów w iOS

W widoku tabeli można wybrać odtwarzanie dźwięku.

Nowy widok otwiera się i tam mam kilka kontrolek takich jak: odtwarzanie, pauza, suwak głośności, suwak postępu, etykieta z bieżącym czasem.

Działa, ale nie jest doskonały. Mogę odtwarzać dźwięk, mogę zatrzymać dźwięk, mogę też użyć suwaka, aby przejść do przodu lub do tyłu. Ale teraz:

Po naciśnięciu przycisku Wstecz na pasku nawigacyjnym utwór jest odtwarzany dalej. W porządku, ale kiedy wrócę do widoku, timer i suwak zresetują się. Nie mogę zatrzymać piosenki, wystarczy poczekać, aż przestanie grać.

Po naciśnięciu przycisku odtwarzania przejdź do widoku tabeli, wybierz inny plik do odtworzenia, pierwszy plik nie przestanie grać.

Oto kod 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 

Oto kod 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 

Oto 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 

A 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

, także [Zobacz firmy Apple Doc.] (Http://developer.apple.com/library/ios/#documentation/mediaplayer/reference/MPMusicPlayerController_ClassReference/Reference/Reference.html) – HDdeveloper

Odpowiedz

9

Proponuję utworzyć globalny obiekt gracza. Ponieważ teraz, za każdym razem, gdy naciskasz ten widok na kontrolerze nawigacyjnym, tworzysz nowy. Oznacza to również, że nie masz żadnych odniesień do poprzedniego gracza (i nie możesz tego zatrzymać). A więc: zadeklaruj AVAudioPlayer o jeden stopień wyżej (w widoku tabeli). Teraz, gdy wybierzesz wiersz, przypisz go do właściwości tego nowego widoku (tego, który podłączyłeś).

Czy pracujesz z storyboardem? Następnie musisz wdrożyć metodę prepareForSegue:. Nadaj swojej serii na storyboardzie identyfikator (np. showPlayer i sprawdź to z if (segue.identifier isEqualToString:@"showPlayer")).

Teraz sprawdź, czy audioPlayer jest zerowe. Jeśli masz

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

Mam nadzieję, że to pomoże.

Również: Nie publikuj zdjęć kodu. Po prostu wstaw kod do swojej odpowiedzi lub opublikuj go w serwisie takim jak pastebin.com i połącz tę stronę z pytaniem. Ułatwia to innym reagowanie i sugestie, jak zmienić kod.

W odpowiedzi na Twój komentarz: Odpowiedni materiał powinien być: W AudioTableViewController.h:

@property (strong, nonatomic) AVAudioPlayer *audioPlayer; 

W 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 dla odpowiedzi. Próbowałem, ale się nie udało. Brzmi to prosto, co powiedziałeś, i ma to sens. Ale po prostu nie rozumiem tego. Mam ogłoszony AVAudioPlayer w AudioTableViewController.h z Audio1DetailViewController.h Potem przeniósł cały kod (nie część viewDidLoad) z Audio1DetailViewController.m do AudioTableViewController.m Ja również zmienił File'sOwner w plik XIB. Mogę odtwarzać utwór, ale nie naciskając przycisku odtwarzania, ale przesuwając suwak postępu. Próbowałem innych rzeczy, ale po dwóch dniach zrezygnowałem i anulowałem wszystkie zmiany. – iHilas

+0

@iHilas Mh, ok. Nie patrząc na twój kod, nie mogę ci tak bardzo pomóc. Czy możesz edytować swoje oryginalne pytanie i dodać jakiś kod (głównie ten kod, który już opublikowałeś jako obraz, ale tym razem jako tekst proszę :)). Aha i jedno: nie sądzę, żebyś musiał tak wiele zmienić. Wszystko pozostaje takie samo, ale zmieniasz "właściciela" twojego odtwarzacza audio na ten widok (w tym sensie, że kontroler ma właściwość strong). Po przejściu do nowego kontrolera przekazujesz referencyjny odtwarzacz audio do nowego kontrolera. –

+0

Dodałem kod – iHilas

1

Zaskakująco MPMoviePlayerController odgrywa również odtwarzacz MP3 ze sterowaniem !!!

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

To jest poprawny i najprostszy sposób radzenia sobie z odtwarzaniem za pomocą elementów sterujących. W iOS8 Apple dodał jeszcze większą elastyczność do tego, co kontrolujesz, które pokazujesz (airplay itp.) –

Powiązane problemy