当 AVAudioPlayer 完成播放时切换 tableview 单元格图像

Posted

技术标签:

【中文标题】当 AVAudioPlayer 完成播放时切换 tableview 单元格图像【英文标题】:Toggle tableview cell image when AVAudioPlayer finishes playing 【发布时间】:2016-08-05 01:12:33 【问题描述】:

我有一个表格视图,每个单元格都有一个播放按钮。播放按钮是UIButton,可在播放和暂停图像之间切换。当按下播放/暂停按钮时,AVAudioPlayer 播放/暂停与单元格关联的音频文件。到目前为止,我的图像完美切换并与音频播放器同步。但是,当音频播放完毕时,我希望图像切换回其默认状态 - 播放按钮图像。

//View controller containing tableview
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 

    let cell = self.audioTable.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! AudioCell

    let track = self.sectionTracks[indexPath.row]

    cell.playButton.addTarget(self, action: #selector(HomeController.playPausePressed(_:)), forControlEvents: UIControlEvents.TouchUpInside)

    var playButtonImage = UIImage(named: "TableViewCellPlayButton84.jpg")
    var pauseButtonImage = UIImage(named: "TableViewCellPauseButton84.jpg")
    playButtonImage = playButtonImage?.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)
    pauseButtonImage = pauseButtonImage?.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)

    cell.playButton.setImage(playButtonImage, forState: UIControlState.Normal)
    cell.playButton.setImage(pauseButtonImage, forState: UIControlState.Selected)
    cell.playButton.selected = false

    return cell


func playPausePressed(sender:UIButton) 

    let pointInTable: CGPoint = sender.convertPoint(sender.bounds.origin, toView: self.audioTable)
    let cellIndexPath = self.audioTable.indexPathForRowAtPoint(pointInTable)
    let track = self.sectionTracks[cellIndexPath!.row]

     //Handle AVAudioPlayer play/pause functionality


//Custom tableview cell file
@IBAction func playPausePressed(sender: UIButton!) 

    if (sender.selected)
    
        sender.selected = false
    
    else
        sender.selected = true
    

【问题讨论】:

【参考方案1】:

您可以订阅成为 AVAudioPlayer 的代理,然后检查音频何时完成。您可以一次播放多个文件或多个文件吗?如果您可以播放多个,则必须跟踪所有正在播放的音频,然后根据委托被触发的时间以及播放器与哪一行相关联来切换该行上的按钮。如果您只能播放一个,那么当用户开始播放音频时,只需保存该行,当音频结束时切换该行的按钮。

https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioPlayerDelegateProtocolReference/

private var xoAssociationKey: UInt8 = 0

extension AVAudioPlayer 
    var name: String! 
        get 
            return objc_getAssociatedObject(self, &xoAssociationKey) as? String
        
        set(newValue) 
            objc_setAssociatedObject(self, &xoAssociationKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
        
    

按照上述方式进行扩展以将名称存储到 AVAudioPlayer 实例可能会有所帮助。然后,您可以在可变字典中跟踪正在播放的音频的名称和单元格的索引路径。当您收到对委托函数optional func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) 的回调时,您可以在字典中查找player.name,这将为您提供该按钮单元格的索引路径。从表格视图中获取单元格,然后切换按钮的选中状态。

编辑

对于一次播放的单个单元格,您可以将变量添加到您的类中,如 var playingAudioIndexPath:NSIndexPath?

当音频开始播放时,将此设置为单击按钮的单元格索引路径。

然后在播放完成事件中,只需抓住单元格并切换按钮

func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer,
                             successfully flag: Bool) 
    guard let indexPath = self.playingAudioIndexPath,
        cell = self.table.cellForRowAtIndexPath(indexPath) as? AudioCell else 
         return;
     

     cell.playButton.selected = false
     self.playingAudioIndexPath = nil

DMC 应用

【讨论】:

谢谢。如果一个单元格的音频文件正在播放,而另一个文件被选中播放,前一个文件将停止播放。我以前使用过audioPlayerDidFinishPlaying,但坦率地说,我的问题是访问cellForRowAtIndexPath 之外的单元格按钮属性。我会试试你的建议。 您应该能够在文件中存储var playingAudioIndexPath:NSIndexPath。一旦音频开始,将此值设置为正在播放索引路径的单元格。然后当 audioPlayerDidFinishPlaying 被调用时,只需调用 if let cell = self.table.cellForRowAtIndexPath(self.playingAudioIndexPath) as? AudioCell // Perform button toggle here on the cell 并将值设置为 nil @Brosef 真棒很高兴能提供帮助!

以上是关于当 AVAudioPlayer 完成播放时切换 tableview 单元格图像的主要内容,如果未能解决你的问题,请参考以下文章

应用程序再次运行时,AVAudioPlayer 不再播放音乐

设备锁定时,AVAudioPlayer 不会播放

iOS - AVAudioPlayer 在后台不会继续播放下一首歌曲

如何让 avaudioplayer 在点击新闻歌曲时停止播放上一首歌曲?

播放 AVAudioPlayer 时游戏卡顿

播放外部音频时暂停 AVAudioPlayer