ios - 返回已传递数据的 UIView

标签 ios xcode audio

我刚刚开始为 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 不再使用,就会调用它。

基于新要求的新编辑:
  • 您希望“正在播放” View 来控制音乐。
  • 即使卸载“正在播放” 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/

    相关文章:

    ios - 如何给图像填充颜色?

    iOS 核心音频生命周期 - AVAudioIONodeImpl.mm :365 -required condition is false: hwFormat

    java - 每10毫秒记录一次音频的音频缓冲区大小和FFT大小是多少?

    ios - 使用 UIPreviewAction 删除项目后如何重新加载 UITableView

    ios - 使用 RxSwift 时未设置 Tableview 数据

    xcode - CocoaPod Storyboard错误 :

    swift - 安装 KDCircularProgress Xcode 9 时遇到问题

    delphi - 波形分析仪的组件或代码

    c# - 在C#中将音频流添加到视频流

    iphone - ios XML解析: Error Domain=NSXMLParserErrorDomain Code=76 on some devices