我刚刚开始为 iOS 开发。言归正传...我创建了一个 UITableViewController 填充了一些我想播放的音频文件。我已成功传递选定的行字符串,并将 View 更改为 UIViewController 的“现在播放 View ”。从那里我使用 avaudioplayer 播放音频。使用嵌入式导航 Controller 返回上一个屏幕后,选择不同的音频跟踪它会创建一个全新的 avaudioplayer 实例,并在旧选择的音频之上播放新选择的音频,而无法停止旧音频。如何创建一个“正在播放” View ,我可以在其中加载新选择的音频并清除旧音频??
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#import <AudioToolbox/AudioToolbox.h>
@interface NowPlayingViewController : UIViewController{
AVAudioPlayer *audioPlayer;
//playPause button images
UIImage *playImg;
UIImage *pauseImg;
IBOutlet UIButton *playPauseButton;
//Volume slider
NSTimer *volumeTimer;
IBOutlet UISlider *volumeSlider;
}
//playPause button action
- (IBAction)playPause:(id)sender;
@end
这是实现文件。
#import "NowPlayingViewController.h"
@implementation NowPlayingViewController
#pragma mark - My actions
//Audio Player Controllers
//Play the selected audio.
- (IBAction)playPause:(id)sender
{
if (![audioPlayer isPlaying]) {
[playPauseButton setImage:pauseImg forState:UIControlStateNormal];
[audioPlayer play];
} else {
[playPauseButton setImage:playImg forState:UIControlStateNormal];
[audioPlayer pause];
}
}
-(void)updateVolumeSlider
{
[audioPlayer setVolume:volumeSlider.value];
}
#pragma mark - Initialization
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
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];
//Instantiate needed variables
playImg = [UIImage imageNamed:@"Play.png"];
pauseImg = [UIImage imageNamed:@"Pause.png"];
//Prepare the audio player
NSString *path = [[NSBundle mainBundle] pathForResource:self.title ofType:@"m4a"];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
[audioPlayer prepareToPlay];
//Setup the volume slider
volumeTimer = [NSTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(updateVolumeSlider) userInfo:nil repeats:YES];
}
主视图标题
#import <UIKit/UIKit.h>
@interface MainTableViewController : UITableViewController{
NSMutableArray *performanceArray;
NSMutableArray *recoveryArray;
}
@end
MainView 实现文件
#import "MainTableViewController.h"
#import "NowPlayingViewController.h"
@implementation MainTableViewController
#pragma mark - Table view
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 2;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
if(section == 0)
return @"Performance";
else
return @"Recovery";
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(section == 0)
return [performanceArray count];
else
return [recoveryArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
if(indexPath.section == 0)
cell.textLabel.text = [performanceArray objectAtIndex:indexPath.row];
else
cell.textLabel.text = [recoveryArray objectAtIndex:indexPath.row];
return cell;
}
#pragma mark - Prepare data to pass
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:@"Audio Selection Segue"])
{
// Get reference to the destination view controller
NowPlayingViewController *np = [segue destinationViewController];
//Pass the selected audio title to the Now Playing View
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:self.tableView.indexPathForSelectedRow];
np.title = cell.textLabel.text;
}
}
#pragma mark - didSelectRowAtIndexPath
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:@"Audio Selection Segue" sender:self];
}
#pragma mark - Initialization
- (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];
//Instantiate performanceArray
performanceArray = [[NSMutableArray alloc]initWithObjects:@"Centering", nil];
//Instantiate recoveryArray
recoveryArray = [[NSMutableArray alloc]initWithObjects:@"Power Nap", nil];
}
最佳答案
第一部分很简单。每次你想将它推送到导航堆栈时,不必实例化一个新的 NowPlayingViewController,只需重用一个现有的。然后,您需要通过 NowPlayingViewController 上的属性传递音频 url。
@interface MyTableViewController {
NowPlayingViewController *nowPlayingViewController;
}
@implementation MyTableViewController{
...
nowPlayingViewController = [[nowPlayingViewController alloc]init];
...
[nowPlayingViewController setAudio:@"urlToAudio"]
this.navigationController.pushViewController(nowPlayingViewController);
...
}
编辑:仅当您按照暗示实例化 viewController 时,上述内容才相关。原来您使用的是 Storyboard,它会自动实例化segues 中的viewsControllers 的新实例。因此问题是你没有停止音乐(见下文)。
关于第二部分(音乐没有停止),您似乎没有在任何地方停止音乐。在“viewDidUnload”或“viewWillDisappear”委托(delegate)调用中这样做,只要 View 不再使用,就会调用它。
基于新要求的新编辑:
在这种情况下,您必须将 AudioPlayer 与 Now Playing View 分开。
每次创建 NowPlaying View 时,您都应该从外部传入 AudioPlayer。理想情况下,您应该有一个类来维护音乐播放器的应用程序状态。
@interface MusicPlayer : NSObject{
}
// example
-(bool) isPlaying;
-(bool) isPaused;
-(void) play;
-(void) pause;
-(void) stop;
-(void) changeTrack;
-(NSString *)currentTrack;
//etc.
@end
然后,当你做你的 segue 时,而不是仅仅告诉你的 NowPlaying View 播放哪个轨道,而是将它传递给 MusicPlayer 实例。
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:@"Audio Selection Segue"])
{
// Get reference to the destination view controller
NowPlayingViewController *np = [segue destinationViewController];
//Pass the selected audio title to the Now Playing View
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:self.tableView.indexPathForSelectedRow];
[self.player stop];
[self.player changeTrack:@"urlToTrack"];
[self.player play];
np.player = self.player;
}
}
现在,让您的按钮简单地向您的音乐播放器发送消息,而不是您的按钮控制播放什么等。使用一些 NSNotification,您甚至可以让音乐播放器向您的 View 发送事件以更新专辑名称、轨道名称、专辑封面等内容。
关于ios - 返回已传递数据的 UIView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8737251/