gpt4 book ai didi

ios - AVAudioPlayer 始终为 null,其 isPlaying 属性始终为 false。播放时文件混合

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:38:26 26 4
gpt4 key购买 nike

过去三天我一直在拔头发来解决这个问题。我检查了很多示例代码,阅读了很多教程,在 stackoverflow 上搜索和检查了很多问题和答案,但我仍然无法解决问题。有几个类似的问题,如 thisthis但他们也没有任何解决方案。

关于我的项目:

我有一个 NIKMasterViewController 和一个 NIKDetailViewController。在第一个中,我在表格 View 中有一个音频文件列表;选择一行,它会导航到 NIKDetailViewController,用户可以在其中查看有关文件的一些信息并播放音频文件。我在 NIKMasterViewController 中定义了一个 AVAudioPlayer 属性并将其设置如下:NIKMasterViewController.h:

@property (nonatomic, strong) AVAudioPlayer *audioPlayer;

NIKMasterViewController.m:

@synthesize audioPlayer;

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:@"showDetail"])
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
NIKDetailViewController *detailViewController = (NIKDetailViewController *) segue.destinationViewController;
[detailViewController setAudioPlayer:audioPlayer];

[detailViewController setFeedEntry:[[[self feedParser] feedItems] objectAtIndex:indexPath.row]];

} else {
NSLog(@"Segue Identifier: %@", segue.identifier);
}

}

这就是关于 NIKMasterViewController 中的 AVAudioPlayer 的全部内容。现在,在我的 NIKDetailViewController 中,我有了 AVAudioPlayer 的另一个属性:

NIKDetailViewController.h:

@property (nonatomic, strong) AVAudioPlayer *audioPlayer;

现在在我的 .m 文件中,我有一个名为 streamAudio 的方法,它在 viewDidLoad 中调用以准备音频播放,并且我有一个 if 条件要求检查 audioPlayer 是否为 nill,如果不是,则 audioPlayer.isPlaying 是否为 true 以便它停止 是播放器,但它从未被调用过,当我导航回 Master VC 以点击另一行以播放另一个文件时,第二个文件开始播放,而第一个文件正在播放,一切都变得困惑。

任何帮助将不胜感激,因为在数小时和数天后仍无法解决此问题后,我几乎要停止编程了!

NIKDetailViewController.m:

@synthesize audioPlayer;


- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
selectedItem = [[NSString alloc]init];
}
return self;
}


#pragma mark - Managing the Audio Playback


- (IBAction)togglePlayingState:(id)button
{
//Handle the button pressing
[self togglePlayPause];
}



- (void)playAudio
{
//Play the audio and set the button to represent the audio is playing
[audioPlayer play];
[playPauseButton setImage:[UIImage imageNamed:@"player_pause"] forState:UIControlStateNormal];
}

- (void)pauseAudio
{
//Pause the audio and set the button to represent the audio is paused
[audioPlayer pause];
[playPauseButton setImage:[UIImage imageNamed:@"player_play"] forState:UIControlStateNormal];

}

- (void)togglePlayPause
{
//Toggle if the music is playing or paused
if (!audioPlayer.playing)
{
[self playAudio];
}
else if (audioPlayer.playing)
{
[self pauseAudio];
}
}


- (void)streamAudio
{
currentFileName = [[feedEntry podcastDownloadURL] lastPathComponent];

NSString* documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString* path = [documentPath stringByAppendingPathComponent:currentFileName];
NSURL* audioURL = [NSURL fileURLWithPath: path];

if (audioPlayer != nil)
{
if (audioPlayer.isPlaying)
{
[audioPlayer stop]; //THIS IS NEVER CALLED
}
audioPlayer = nil; //THIS IS NEVER CALLED
}

audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:nil];

// Set a timer which keep getting the current music time and update the UISlider in 1 sec interval
playbackTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateSlider) userInfo:nil repeats:YES];
// Set the maximum value of the UISlider
seekSlider.maximumValue = audioPlayer.duration;


currentTime.text = [NSString stringWithFormat:@"%d:%02d", (int)audioPlayer.currentTime / 60, (int)audioPlayer.currentTime % 60, nil];
remainingTime.text = [NSString stringWithFormat:@"%d:%02d", (int)(audioPlayer.duration - audioPlayer.currentTime) / 60, (int)(audioPlayer.duration - audioPlayer.currentTime) % 60, nil];

// Set the valueChanged target
[seekSlider addTarget:self action:@selector(sliderChanged:) forControlEvents:UIControlEventValueChanged];
audioPlayer.delegate = self;
[audioPlayer prepareToPlay]; //Add the audio to the memory.
}


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

- (IBAction)sliderChanged:(UISlider *)sender {
// Fast skip the music when user scrolls the slider
[audioPlayer stop];
[audioPlayer setCurrentTime:seekSlider.value];
audioPlayer.delegate = self;

[audioPlayer prepareToPlay];
[audioPlayer play];
}

// Stop the timer when the music is finished (Need to implement the AVAudioPlayerDelegate in the Controller header)
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
// Music completed
if (flag) {
[playbackTimer invalidate];
}
}


- (IBAction)forwardAudio:(id)sender
{
int currentTime = [audioPlayer currentTime];
[audioPlayer setCurrentTime:currentTime+10];
}

- (IBAction)rewindAudio:(id)sender
{
int currentTime = [audioPlayer currentTime];
[audioPlayer setCurrentTime:currentTime-10];
}


//Make sure we can recieve remote control events
- (BOOL)canBecomeFirstResponder {
return YES;
}

- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
//if it is a remote control event handle it correctly
if (event.type == UIEventTypeRemoteControl) {
if (event.subtype == UIEventSubtypeRemoteControlPlay) {
[self playAudio];
} else if (event.subtype == UIEventSubtypeRemoteControlPause) {
[self pauseAudio];
} else if (event.subtype == UIEventSubtypeRemoteControlTogglePlayPause) {
[self togglePlayPause];
}
}
}

#pragma mark - view life cycle


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

//Once the view has loaded then we can register to begin recieving controls and we can become the first responder
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
}

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

//End recieving events
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
[self resignFirstResponder];
}

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

[self streamAudio];

//Make sure the system follows our playback status - to support the playback when the app enters the background mode.
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];

}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end

注意:我曾尝试将 Detail VC 中的属性设置为 weak 但随后,我收到警告,并且属性在我可以播放文件之前被释放.

最佳答案

所以...我终于可以通过创建 audioplayersingleton 来解决这个问题。这是这样的:

  1. 首先,我从我的 NIKMasterViewController 类中删除了所有与 audioPlayer 相关的代码,其中包括 audioPlayer 声明和设置在 prepareForSegue 中。
  2. 我创建了一个名为 NIKAudioPlayer 的新类。
  3. NIKAudioPlayer.h 中:

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

    @interface NIKAudioPlayer : NSObject <AVAudioPlayerDelegate>
    {
    AVAudioPlayer *currentPlayer;
    }
    @property (nonatomic, strong) AVAudioPlayer *currentPlayer;
    +(NIKAudioPlayer *) sharedPlayer;
    -(void)playURL:(NSURL*)url;
    @end
  4. NIKAudioPlayer.m 中:

    #import "NIKAudioPlayer.h"

    @implementation NIKAudioPlayer
    @synthesize currentPlayer;

    +(NIKAudioPlayer *) sharedPlayer
    {
    static NIKAudioPlayer* sharedPlayer;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
    sharedPlayer = [[NIKAudioPlayer alloc] init];
    });
    return sharedPlayer;
    }

    -(void)playURL:(NSURL*)url
    {
    [currentPlayer stop];
    currentPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
    [currentPlayer prepareToPlay];
    }

    @end
  5. 现在在代码的其他任何地方(在我的例子中是 NIKDetailViewController)每当我需要播放音频文件时,我从 调用 sharedPlayer >NIKAudioPlayer:

    [[NIKPlayer sharedPlayer] playURL:audioURL];
    [[NIKPlayer sharedPlayer].currentPlayer prepareToPlay];

简而言之,将 NIKDetailViewController 中的所有 audioPlayer 替换为 [NIKPlayer sharedPlayer].currentPlayer,甚至将其转换并使用它无处不在:

audioPlayer = [NIKPlayer sharedPlayer].currentPlayer

关于ios - AVAudioPlayer 始终为 null,其 isPlaying 属性始终为 false。播放时文件混合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20164873/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com