将事件传递给UITableView之外的UITableViewCell

时间:2017-12-01 15:33:19

标签: ios swift uitableview avplayer

我有一个应用程序,显示UITableView上的播客剧集列表。每个单元格都使用扩展UITableViewCell的自定义类进行管理,每个单元格都有自己的AVAudioPlayer实例来控制剧集的播放。我想做的是下一个:

当我点击剧集上的播放时,如果有其他剧集播放,则停止播放,然后开始新剧集。

我所做的是在UITableViewCell上创建一个协议,只要按下播放按钮就会触发事件。然后在我的UIViewController上实现了该协议,并使用cellForRowAt获取最新选定的单元格(我保留对最新选择的IndexPath的引用)并调用pause方法。这似乎工作,但后来我意识到,只有当两个单元格在屏幕上都可见时,它才有效。每当我想要一个不在屏幕上的cellForRowAt的单元格时,该方法返回null并且我无法更新单元格,这导致两个单元格同时播放声音。

这是我的单元格代码:

@IBAction func playbackButtonHandler(_ sender: UIButton) {
    guard let audioPlayer = self.player else {
        self.downloadAudio(forPodcast: podcast.id)
        return
    }
    guard let cellIndex = indexPath else { return }
    if (audioPlayer.isPlaying) {
        audioPlayer.pause()
        delegate?.onPauseActionSelected(forRow: cellIndex)
    } else {
        audioPlayer.play()
        delegate?.onPlayActionSelected(forRow: cellIndex)
    }
    sender.isSelected = !sender.isSelected
}

和ViewController:

func onPlayActionSelected(forRow row: IndexPath) {
    if let activeItem = self.activePodcast {
        if row != activeItem {
            guard let activeCell = self.tableView.cellForRow(at: activeItem) as? PodcastCell else { return }
            activeCell.playbackButtonHandler(activeCell.playbackButton)
        }
    }
    self.activePodcast = row
}

有更好的方法吗?

修改

尝试了Larme的建议,并在ViewController中为AVAudioController创建了一个单例,用于处理同时播放两个音轨的问题。但是,这仍然存在如何更新单元格控件的问题,因为暂停按钮仍然可见,就像它仍在播放音频一样。 请参阅图像以获得澄清:

我有一个不再在屏幕上播放音频的单元格。然后我点击第一个单元格上的播放。音频停止并开始在第一个单元格上播放

I have a cell that is not in the screen anymore playing audio. Then I click play on the first cell. Audios stops and starts playing on the first cell

现在我滚动到底部,虽然单元格不再播放,但暂停按钮仍然可见。我需要一种方法来调用单元格来改变该按钮的状态

Now I scroll to the bottom and although the cell is not playing anymore, the pause button is still visible. I need a way to call the cell to change that button's state

1 个答案:

答案 0 :(得分:1)

因此修复了2个问题中的一个,即同时播放2个音频。现在第二个问题,即刷新UI。您应该在正在播放音频的单元格中显示暂停按钮,而播放按钮将替换最后一个播放单元格中的暂停按钮。

现在您不需要在 onPlayActionSelected 方法中调用cellForRow。而是在tableview的cellForRowAt委托方法中编写代码。因为如果该单元格不可见,您不需要立即更改前一单元格的暂停按钮,只有当用户向下滚动到该位置时,您需要更改暂停按钮以播放按钮,因此用户不会看到差异。

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let activeCell = /* Deque your tableViewCell with its subclass */

    if let activeItem = self.activePodcast {
        if indexPath.row == activeItem {
            activeCell.buttonImageView.image = UIImage(named: "Play")!
        }else  {
            activeCell.buttonImageView.image = UIImage(named: "Pause")!
        }
    }

    return activeCell
}