UISlider&自定义tableviewcell上的UILabels在第二次播放音频之前不会使用avaudioplayer进行更新

时间:2017-08-13 14:45:57

标签: ios objective-c avaudioplayer uislider

背景:我有一个UITableView,最初加载一些标准的UITableViewCells。单击其中一个时,将重新加载该表,但单击的单元格将成为名为“RecordingTableCell”的自定义子类,该子类具有2个UILabel,一个UIButton和一个UISlider。目前工作正常。

按下按钮时,会设置AVAudioPlayer并播放声音文件。但是,执行此操作的方法([self setupAudio])也会获得2个UILabel和UISlider,以便可以使用音频的进度更新它们(我不确定我是否以正确的方式获取它们)。 / p>

首次按下播放按钮时,会播放音频,但滑块或标签根本不会改变。但是,在音频结束后(即一旦调用了audioPlayerDidFinishPlaying),如果再次按下播放按钮,一切都按预期工作。

The code running in the simulator

这是代码:(抱歉大块!)

...

-(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'子视图是否出错,或者如果设置音频时出错则播放器。

任何帮助将不胜感激!

2 个答案:

答案 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方法,则重新实例化子视图。