在iOS中使用控件播放音频 [英] Playing audio with controls in iOS

查看:115
本文介绍了在iOS中使用控件播放音频的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用标签栏,导航栏和表格视图创建了一个应用程序。



在表格视图中,您可以选择收听某些音频。



新视图打开,我有一些控件如:播放,暂停,音量滑块,进度滑块,标签与当前时间。



它有效但不完美。
我可以播放音频,我可以暂停音频,我也可以使用滑块向前或向后跳过。但是现在:



当我按下导航栏上的返回按钮时,歌曲会继续播放。没关系,但是当我再次回到视图时,计时器和滑块自行重置。我不能暂停这首歌,只需要等待它停止播放。



另外,当我点击播放时,回到表格视图,选择要播放的另一个文件,第一个文件不会停止播放



这是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(非原子,保留)IBOutlet UISlider * volumeControl;
@property(非原子,保留)IBOutlet UILabel * timerLabel;
@property(非原子,保留)IBOutlet UISlider * progressBar;
@property(nonatomic,retain)NSTimer * playbackTimer;
@property(nonatomic,retain)AVAudioPlayer * audioPlayer;
- (IBAction)playAudio;
- (IBAction)stopAudio;
- (IBAction)adjustVolume;
- (IBAction)sliderChanged;

@end

这是Audio1DetailViewController.m代码:

  #importAudio1DetailViewController.h


@implementation Audio1DetailViewController

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

- (void)playAudio
{
playbackTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:@selector(updateTime)
userInfo:nil
重复:是];
[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 - (分钟* 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,
分钟,秒,
duration_minutes,duration_seconds];

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

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

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

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

if(error)
{
NSLog(@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;
//设置valueChanged目标
[progressBar addTarget:self action:@selector(sliderChanged :) forControlEvents:
UIControl EventValueChanged];
}

- (void)updateSlider {
//更新关于音乐时间的滑块
progressBar.value = audioPlayer.currentTime;
}

- (IBAction)sliderChanged:(UISlider *)sender {
//当用户滚动UISlider
[audioPlayer stop]时快速跳过音乐;
[audioPlayer setCurrentTime:progressBar.value];
[audioPlayer prepareToPlay];
[audioPlayer play];
}

- (无效)audioPlayerDidFinishPlaying:
(AVAudioPlayer *)播放器成功:(BOOL)标志
{
}


- (void)audioPlayerDecodeErrorDidOccur:
(AVAudioPlayer *)播放器错误:(NSError *)错误
{
}
- (void)audioPlayerBeginInterruption:(AVAudioPlayer *)玩家
{
}
- (无效)audioPlayerEndInterruption:(AVAudioPlayer *)玩家
{
}

- (无效) viewDidUnload {
audioPlayer = nil;
volumeControl = nil;

}

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

@end

这是AudioTableViewController.h

  #import< UIKit / UIKit.h> 

@class Audio1DetailViewController;


@interface AudioTableViewController:UITableViewController
< UITableViewDelegate,UITableViewDataSource> {


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

@property(非原子,保留)NSMutableArray * audioArray;
@property(nonatomic,retain)Audio1DetailViewController * audio1DetailViewController;

@end

和AudioTableViewController.m

  #importAudioTableViewController.h
#importAudio1DetailViewController.h

#importDEQAppDelegate.h

@implementation AudioTableViewController
@synthesize audioArray;
@synthesize audio1DetailViewController;

- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if(self){
//自定义初始化
{
返回self;
}

- (void)didReceiveMemoryWarning
{
//如果视图没有超视图,则释放视图。
[super didReceiveMemoryWarning];

//释放未使用的任何缓存数据,图像等。
}

#pragma mark - 查看生命周期

- (void)viewDidLoad {
[super viewDidLoad];
self.title = NSLocalizedString(@Audio,@Audio);
self.audioArray = [[NSArray alloc] initWithObjects:
@1。Het Begin,@2。De Mensen,// etcetera
nil];
//取消注释以下行以保留演示文稿之间的选择。
self.clearsSelectionOnViewWillAppear = NO;

//取消注释以下行,以在此
视图控制器的导航栏中显示编辑按钮。
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}

- (void)viewDidUnload
{
[super viewDidUnload];
//释放主视图的所有保留子视图。
self.audioArray = nil;
}

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

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

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

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

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
//为支持的方向返回YES
return(interfaceOrientation == UIInterfaceOrientationPortrait) ;
}

#pragma mark - 表视图数据源

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
#警告可能不完整的方法实现。
//返回部分的数量。
返回1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
#warning不完整的方法实现。
//返回该部分中的行数。
返回[self.audioArray count];
}

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

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

//配置单元格...
cell.textLabel.text = [self.audioArray objectAtIndex:[indexPath row]];

返回单元格;
}

#pragma mark - 表视图委托

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//导航逻辑可能会在这里。创建并推送另一个视图控制器。

NSUInteger row = indexPath.row;

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

}

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

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

@end


解决方案

我建议你创建一个全局播放器对象。因为现在,每次在导航控制器上推送此视图时,都会创建一个新视图。这也意味着您没有任何对前一个玩家的引用(并且无法阻止它)。所以:声明AVAudioPlayer更高一步(在tableview中)。现在,当您在其中选择一行时,将其分配给此新视图的属性(您链接的属性)。



您是否使用故事板?然后你必须实现方法 prepareForSegue:。在故事板上给你的segue一个标识符(比如 showPlayer 并用检查if if(segue.identifier isEqualToString:@showPlayer))。



现在在 viewDidLoad 中检查 audioPlayer 是零。如果你

   - (void)viewDidLoad 
{
[super viewDidLoad];
if(audioPlayer == nil)
{
//你的init(audioplayer = [[AVAudioPlayer ...
}
else
{
if(audioPlayer.isPlaying)
{
//即暂停播放器或做其他事情
}
}
}

希望这可以帮到你。



同时:不要发布代码图片。只需在回复中插入代码或将代码发布到像pastebin.com这样的网站,并在您的问题中链接该页面。这样,其他人就可以更轻松地回复并提出如何更改代码的建议。 / p>

回复你的评论
相关的东西应该是:
在AudioTableViewController.h中

  @property(强,非原子)AVAudioPlayer * audioPlayer; 

在AudioTableViewController.m中

  @synthesize audioPlayer; 
...
- (void)t ableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//导航逻辑可能会在这里。创建并推送另一个视图控制器。

NSUInteger row = indexPath.row;

if(row == 0)
{
self.audio1DetailViewController = [[Audio1DetailViewController alloc] initWithNibName:@Audio1DetailViewControllerbundle: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:@001FatihaofType:@MP3]];

NSError *错误;

//这是重要的部分:如果我们已经玩了一些东西,那就停下吧!
if(audioPlayer!= nil)
{
[audioPlayer stop];
}
//其他一切都应该正常发生。
audioPlayer = [[AVAudioPlayer alloc]
initWithContentsOfURL:url
error:& error];

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


I've made an app with tab bar,nav bar and table view.

In the table view you can choose to listen to some audio.

New view opens and there I have some controls like: play,pause,volume slider, progress slider, label with the current time.

It works, but not perfect. I can play the audio, I can pause the audio, I can also use the slider to skip forward or back. But now:

When I hit the Back button on the navbar, the song keeps playing. That's ok, but when I go back to the view again, the timer and the slider reset themselves. I can't pause the song, just need to wait util it stops playing.

Also, when I hit play, go back to the table view, choose another file to play, the first file won't stop playing.

Here is the Audio1DetailViewController.h code:

     #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

Here is the Audio1DetailViewController.m code:

     #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

Here is the 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

And the 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

解决方案

I would suggest you create a global player object. Because right now, each time you push this view on the navigation controller you create a new one. This also means that you do not have any reference to the previous player (and can not stop it). So: declare the AVAudioPlayer one step higher (in the tableview). Now, when you select a row in it, assign it to a property of this new view (the one you linked).

Do you work with storyboard? Then you have to implement the method prepareForSegue:. Give your segue on the storyboard an identifier (like showPlayer and check for that with if (segue.identifier isEqualToString:@"showPlayer")).

Now in your viewDidLoad do a check if audioPlayer is nil. If you

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

Hope this helps you.

Also: Do not post images of code. Just insert the code in your response or post it to a site like pastebin.com and link that page in your question. This makes it easier for others to respond and make suggestions how to alter your code.

In response to your comment: The relevant stuff should be: 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];

这篇关于在iOS中使用控件播放音频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆