如何使用Swift处理tableView单元格音频播放和暂停按钮?

时间:2018-11-08 04:30:33

标签: ios swift tableview

我的情况是,我recording audiosave进入Coredata,然后listing进入tableView,其中customcell播放/暂停单个按钮。我不能做下面的事情

  1. 检测playback的结尾并更改audio play单元格按钮图像暂停以播放
  2. 在第一行cell音频播放时间中,如果用户单击第二行播放按钮,则需要stop第一行单元格音频播放并更改图像暂停以播放 然后second row单元格按钮播放即可暂停

如何执行以上两个操作?

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

        let cellIdentifier = "Cell"
        let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! CustomCell

        // Configure the cell...            
        cell.likeBtn.addTarget(self, action: #selector(TableViewController.liked), for: .touchUpInside)

        return cell
}

@objc func liked(sender: UIButton) {
        // Here I need to change button icon and handle row
}

1 个答案:

答案 0 :(得分:1)

在不了解应用程序其余部分的情况下很难解释。提供更多的上下文很重要。假设某些事情,我会尽力为您解答。

首先,我假设您有Song个看起来像这样的对象:

public struct Song: Equatable {
    let name: String
    let fileName: String
}

您的数据库具有以下公共方法和属性:

class DB {
  func getSong(_ position: Int) -> Song?
  func getPosition(_ song: Song) -> Int?
  var count: Int
}

为了便于在init上使用此示例代码,需要初始化一些预定义数据。

还有一个Player对象,该对象通过以下公共方法管理音频的播放:

class Player {
  func currentlyPlaying() -> Song?
  func play(this song: Song)
  func stop()
}

现在,使用先前定义的内容,我创建了一个自定义单元格,以显示数据库中每个Song的名称和按钮。定义是这样的:

class CustomCell : UITableViewCell {
  @IBOutlet weak var label: UILabel!
  @IBOutlet weak var button: UIButton!
}

外观如下:

Prototype custom cell

接下来,让我们定义表视图的数据源方法。在每个单元格中,为每个按钮的touchUpInside事件添加一个目标(如您在问题中定义的那样)。

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  return DB.shared.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell",  
                                           for: indexPath) as! CustomCell
  cell.label.text = DB.shared.getSong(indexPath.row)!.name
  cell.button.addTarget(self, action: #selector(buttonTapped(_:)),
                        for: .touchUpInside)
  return cell
}

接下来,让我们定义一个辅助方法,以在UIVIew中定位TableView。通过这种方法,我们可以获得IndexPath中任何单元格内任何控件的TableView。返回值是可选的,以便在找不到nil时返回。

func getViewIndexInTableView(tableView: UITableView, view: UIView) -> IndexPath? {
  let pos = view.convert(CGPoint.zero, to: tableView)
  return tableView.indexPathForRow(at: pos)
}

定义了另一个帮助器方法,以通过动画更改按钮的图像:

func changeButtonImage(_ button: UIButton, play: Bool) {
  UIView.transition(with: button, duration: 0.4,
                    options: .transitionCrossDissolve, animations: {
    button.setImage(UIImage(named: play ? "Play" : "Stop"), for: .normal)
  }, completion: nil
}

需要一种方法来停止当前播放的歌曲。第一件事是检查歌曲是否正在播放,如果是,则调用Player的stop方法。然后,让我们定位数据库中Song的位置,在我的情况下,该位置对应于TableView中的位置;让我们创建一个IndexPath来获取相应的单元格,最后用该单元格的按钮调用changeButtonImage来更改图像。

func stopCurrentlyPlaying() {
  if let currentSong = Player.shared.currentlyPlaying() {
    Player.shared.stop()
      if let indexStop = DB.shared.getPosition(currentSong) {
        let cell = tableView.cellForRow(at: IndexPath(item: indexStop, section: 0)) as! CustomCell
        changeButtonImage(cell.button, play: true)
      }
  }
}

开始播放歌曲的buttonTapped方法内部有一些逻辑。首先,方法签名需要@objc才能在addTarget方法中使用。逻辑如下:

  1. 使用助手方法在表格视图中本地化按钮的IndexPath
  2. 在数据库中本地化歌曲,表中的行号与数据库中的顺序相对应。
  3. 如果当前正在播放一首歌曲,并且与所点击按钮的本地化歌曲相同,则意味着我们只想停止播放歌曲,因此调用stopCurrentlyPlaying并返回方法。
  4. 如果不是同一首歌曲,或者没有播放任何歌曲,请打电话:stopCurrentlyPlaying,开始播放新歌曲,然后将轻按的按钮的图像更改为“停止”图像。

代码如下:

@objc func buttonTapped(_ sender: UIButton) {
  // Let's localize the index of the button using a helper method
  // and also localize the Song i the database
  if let index = getViewIndexInTableView(tableView: tableView, view: sender),
      let song = DB.shared.getSong(index.row) {
      // If a the song located is the same it's currently playing just stop
      // playing it and return.
      guard song != Player.shared.currentlyPlaying() else {
          stopCurrentlyPlaying()
          return
      }
      // Stop any playing song if necessary
      stopCurrentlyPlaying()
      // Start playing the tapped song
      Player.shared.play(this: song)
      // Change the tapped button to a Stop image
      changeButtonImage(sender, play: false)
  }
}

以下是示例应用程序的视频片段:sample app