背景:我有一个UITableView,最初加载一些标准的UITableViewCells。单击其中一个时,将重新加载该表,但单击的单元格将成为名为“RecordingTableCell”的自定义子类,该子类具有2个UILabel,一个UIButton和一个UISlider。目前工作正常。
按下按钮时,会设置AVAudioPlayer并播放声音文件。但是,执行此操作的方法([self setupAudio]
)也会获得2个UILabel和UISlider,以便可以使用音频的进度更新它们(我不确定我是否以正确的方式获取它们)。 / p>
首次按下播放按钮时,会播放音频,但滑块或标签根本不会改变。但是,在音频结束后(即一旦调用了audioPlayerDidFinishPlaying),如果再次按下播放按钮,一切都按预期工作。
这是代码:(抱歉大块!)
...
-(void)setupAudio
{
//Get path
recordingPaths = [[NSUserDefaults standardUserDefaults] objectForKey:@"recordingPaths"];
recordedAudioURL = [NSURL URLWithString:recordingPaths[selectedRowIndex.row]];
NSError *audioError;
player = [[AVAudioPlayer alloc] initWithContentsOfURL:[self recordedAudioURL] error:&audioError];
player.delegate = self;
[player prepareToPlay];
recordingCurrentCell = (RecordingTableCell *)[self.tableView viewWithTag:REC_TABLE_CELL_TAG];
//The following are subviews of recordingTableCell
currentTimeLabel = [recordingCurrentCell currentTimeLabel];
totalTimeLabel = [recordingCurrentCell totalTimeLabel];
slider = [recordingCurrentCell progressSlider];
//Setup slider & labels
slider.maximumValue = [player duration];
totalTimeLabel.text = [NSString stringWithFormat:@"%.1f", player.duration];
slider.value = 0.0;
currentTimeLabel.text = [NSString stringWithFormat:@"%.1f", slider.value];
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
selectedRowIndex = indexPath;
rowSelected=YES;
//Update the table so that the row with an indexPath equal to 'selectedRowIndex' becomes a custom subclass of UITableViewCell
[tableView beginUpdates];
[self.tableView reloadData];
[tableView endUpdates];
if(!player)
{
if(selectedRowIndex.row!=indexPath.row)
{
[[self player] stop];
player=nil;
//Change button on selected cell to the 'play' image
[actionButton setImage:[UIImage imageNamed:@"play.png"] forState:UIControlStateNormal];
//If the NSTimer is still going, invalidate it
if(timer)
{
[timer invalidate];
timer = nil;
}
}
}
[self setupAudio];
}
//This is hooked up to the button on the custom tableviewcell
- (IBAction)actionButtonPressed:(id)sender
{
actionButton = (UIButton *)sender;
if(!player.playing)
{
[actionButton setImage:[UIImage imageNamed:@"pause.png"] forState:UIControlStateNormal];
[timer invalidate];
timer = nil;
[player play];
timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(updateTime:) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}
else
{
if(timer)
{
[timer invalidate];
timer = nil;
}
[actionButton setImage:[UIImage imageNamed:@"play.png"] forState:UIControlStateNormal];
[player pause];
}
}
//This is connected to the slider on the custom tableviewcell.
- (IBAction)slide:(id)sender
{
if(player)
{
player.currentTime = slider.value;
}
currentTimeLabel.text = [NSString stringWithFormat:@"%.1f", slider.value];
}
- (void)updateTime:(NSTimer *)timer
{
if(player)
{
slider.value = player.currentTime;
currentTimeLabel.text = [NSString stringWithFormat:@"%.1f", slider.value];
}
}
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
if(timer)
{
[timer invalidate];
timer = nil;
}
[self setupAudio];
[actionButton setImage:[UIImage imageNamed:@"play.png"] forState:UIControlStateNormal];
}
我试过移动一些比特并且我不确定在[self setupAudio]中获取'RecordingTableCell'子视图是否出错,或者如果设置音频时出错则播放器。
任何帮助将不胜感激!
答案 0 :(得分:2)
我认为播放器的当前/持续时间是双重类型,您可以使用以下方法将其作为字符串:
func getTimeString(from duration:Double) -> String{
let hours = Int(duration / 3600)
let minutes = Int(duration / 60) % 60
let seconds = Int(duration.truncatingRemainder(dividingBy: 60))
if hours > 0 {
return String(format: "%:%02i:%02i", arguments: [hours,minutes,seconds])
}else {
return String(format: "%02i:%02i", arguments: [minutes,seconds])
}
}
当前时间字符串:
func getCurrentTimeAsString() -> String{
guard let time = player?.currentTime else {
return "00:00"
}
return getTimeString(from: time)
}
总时间字符串:
func getDurationAsString() -> String{
guard let time = player?.duration else {
return "00:00"
}
return getTimeString(from: time)
}
获取流程价值
func getProgressValue()->Float{
var theCurrentTime = 0.0
var theDuration = 0.0
if let currentTime = player?.currentTime,let duration = player?.duration {
theCurrentTime = currentTime
theDuration = duration
}
return Float(theCurrentTime / theDuration)
}
你需要使用Timer来更新当前的Time标签文本,不要忘记停止计时器。
timer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true, block: {[unowned self] (timer:Timer) in
self.updateUIWithTimer()
})
func updateUIWithTimer(){
currentTimeLabel.text = getCurrentTimeAsString()
timeSlider.value = getProgressValue()
}
答案 1 :(得分:0)
我不太确定这是否是正确的方法(也就是说我可能会缺少更基本的东西),但我设法通过创建一个布尔变量来解决问题,以确定是否是第一次为录制设置AVAudioPlayer,如果是actionButtonPressed
方法,则重新实例化子视图。