我试图以编程方式创建AVAudioplayer
。音频播放器播放成功。但我有一些问题。我在UITableview中显示12个音频项目。如果我点击第一项,它会导航到音频播放器视图控制器。然后我点击播放按钮,歌曲就会播放。如果我点击后退按钮,歌曲继续播放。但是如果我再次点击相同的项目音频视图控制器,视图将显示初始状态,如进度条不应该移动,当前时间和歌曲持续时间是空的。但歌曲不停地播放。还有一个问题。如果我点击第一个项目,相应的歌曲将播放。我不应该点击任何pass按钮。我点击后退按钮,然后点击第二项。如果我点击第二项音频视图控制器就会显示出来。我点击播放按钮,歌曲显示。在后台播放第一首歌和第二首歌。这是我的第二个问题。如何解决这两个问题。请任何人帮助我。
-(void)playOrPauseButtonPressed:(id)sender
{
if(playing==NO)
{
[playButton setBackgroundImage:[UIImage imageNamed:@"Pause.png"] forState:UIControlStateNormal];
// Here Pause.png is a image showing Pause Button.
NSError *err=nil;
AVAudioSession *audioSession=[AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
NSLog(@"%@ %d",urlsArray,selectedIndex);
NSString *sourcePath=[urlsArray objectAtIndex:selectedIndex];
NSData *objectData=[NSData dataWithContentsOfURL:[NSURL URLWithString:sourcePath]];
audioPlayer = [[AVAudioPlayer alloc] initWithData:objectData error:&err];
audioPlayer.numberOfLoops = 0;
[audioPlayer prepareToPlay];
audioPlayer.delegate=self;
[audioPlayer play];
playing=YES;
}
else if (playing==YES)
{
[playButton setBackgroundImage:[UIImage imageNamed:@"play.png"] forState:UIControlStateNormal];
[audioPlayer pause];
playing=NO;
}
if (self.audioPlayer)
{
[self updateViewForPlayerInfo];
[self updateViewForPlayerState];
[self.audioPlayer setDelegate:self];
}
}
-(void)updateViewForPlayerInfo
{
self.songDuration.text = [NSString stringWithFormat:@"%d:%02d", (int)self.audioPlayer.duration / 60, (int)self.audioPlayer.duration % 60, nil];
NSLog(@"%f", self.audioPlayer.duration);
self.progressBar.maximumValue = self.audioPlayer.duration;
self.volumeSlider.value = self.audioPlayer.volume;
}
-(void)updateViewForPlayerState
{
[self updateCurrentTime];
if (self.updatedTimer)
{
[self.updatedTimer invalidate];
}
if (self.audioPlayer.playing)
{
self.updatedTimer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(updateCurrentTime) userInfo:self.audioPlayer repeats:YES];
}
}
-(void)updateCurrentTime
{
//NSLog(@"self.audioPlayer.currentTime = %f", self.audioPlayer.currentTime);
self.currentTime.text = [NSString stringWithFormat:@"%d:%02d", (int)self.audioPlayer.currentTime / 60, (int)self.audioPlayer.currentTime % 60, nil];
self.progressBar.value = self.audioPlayer.currentTime;
}
-(void)volumeSliderMoved:(UISlider *)sender
{
self.audioPlayer.volume=[sender value];
}
我认为问题就在这里
audioPlayer = [[AVAudioPlayer alloc] initWithData:objectData error:&err];
每次创建audioPlayer对象时。所以我的建议是在创建像这样的对象之前检查audioPlayer
if(audioPlayer)
{
audioPlayer.delegate=nil;
audioPlayer=nil;
}
然后创建对象。
简而言之,情况如下:
- 点击表格单元格
- 你创建了一个音频播放器视图控制器
- 你播放音频-你的音频播放器本身保留了一些原因(不清楚为什么-你使用ARC?)
- 你点击后退按钮-音频播放器视图控制器被释放
- 你再次点击表格单元格-并创建一个新的音频播放器视图控制器与它自己的播放器!
基本上-如果你想要之前的歌曲继续播放,即使你退出音频播放器视图控制器-并且只有一个播放器的音频-我会保持它在一个单一的类,将管理播放器,或作为一个应用程序委托的属性。
这样,当你进入Audio Player视图控制器时,它将检查以下内容:
- 如果一个球员不存在-创建它并分配它的项目-准备播放
- 如果玩家存在,但它是相同的项目-只需更新控件显示它当前的播放状态。
- 如果播放器存在,但它是另一个项目-要么不更新控件-当用户点击播放时-替换播放器中的项目并开始更新控件-或者在显示音频播放器视图控制器时停止歌曲。(取决于你-我显然不知道你的应用程序的设计)
在使用AVAudioPlayer时,我使用属性来跟上播放器。基于查看你的代码,我不清楚你是否让玩家留在身边,或者你是否每次都实例化一个新实例。根据你的描述,这听起来像你正在实例化一个新的实例-不要认为你想要这样。
在你的。h文件中,像这样:@property (nonatomic, strong) AVAudioPlayer *myAVAudioPlayer;
,然后在你的。m文件中相应的@synthesize。
当您想从一首歌曲移动到下一首时,只需停止播放当前-然后使用init为您自己重新加载一个新的URL。myAVAudioPlayer财产。然后你必须为AVAudioPlayer选项再次调用prepareToPlay方法。
你可能会通过不管理关于玩或不玩的变量来让自己更容易(看起来你在你的帖子中这样做了)。使用你的属性并通过访问属性的setter/getter来检查玩家的状态:
if(!self.myAVAudioPlayer)
{
// allocate and initialize using the code you have
[self.myAVAudioPlayer prepareToPlay];
} else
if ([self.myAVAudioPlayer isPlaying])
{
//do whatever you need for isPlaying - looks like pause
} else
if (![self.myAVAudioPlayer isPlaying])
{
// do whatever you need to do if the player isn't playing when the button is pressed
// at this point you will likely just re-init with a new URL and reset other items
// don't forget to call -prepareToPlay again
}
这里是另一个方法的链接,利用AVPlayerItem ->点击https://stackoverflow.com/a/22254588/3563814