如何在每个tableviewCell中管理AVAudioPlayer isPlaying?

时间:2017-08-07 08:20:03

标签: ios swift uitableview avaudioplayer

我有一个tableview,并且tableView中有多个单元格 每个单元格都有一个AVAudioPlayer项目 我遇到了一个问题 我不知道如何管理AVAudioPlayer 当我第一次播放AVAudioPlayer,然后播放第二个AVAudioPlayer时,声音会重叠 如何在我的自定义单元格中停止第一个AVAudioPlayer,并播放第二个AVAudioPlayer? 感谢。

这是我的自定义单元格:

class TableViewCell: UITableViewCell {

@IBOutlet weak var myImageView: UIImageView!
@IBOutlet weak var myChatBubbleView: UIView!
@IBOutlet weak var myDateLabel: UILabel!
@IBOutlet weak var mySecondLabel: UILabel!
@IBOutlet weak var myRecordPlayerBtn: MenuButton!
private var timer:Timer?   
private var elapsedTimeInSecond:Int = 0
var audioPlayer:AVAudioPlayer?
var message:ChatroomMessage?
var chatroomId:String = ""
var delegate:PlayRecordDelegate?

override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code

    self.backgroundColor = defaultBackgroundColor
    self.tintColor = defaultChatroomCheckButtonColor

    myImageView.layer.masksToBounds = true 
    myImageView.layer.cornerRadius = defaultIconRadius

    myChatBubbleView.backgroundColor = defaultChatGreenBubbleColor
    myChatBubbleView.layer.cornerRadius = defaultButtonRadius

    myDateLabel.textColor = defaultChatTimeColor

    mySecondLabel.textColor = defaultChatTimeColor
    mySecondLabel.isHidden = true

    myRecordPlayerBtn.imageView?.animationDuration = 1
    myRecordPlayerBtn.imageView?.animationImages =  [
    UIImage(named: "img_myRocordPlaying1")!,
    UIImage(named: "img_myRocordPlaying2")!,
    UIImage(named: "img_myRocordPlaying3")!
    ]
}

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
}

func loadByMessage(_ message:ChatroomMessage, chatroomId:String) {
    self.message = message
    self.chatroomId = chatroomId

    myRecordPlayerBtn.addTarget(self, action: #selector(recordPlay), for: .touchUpInside)
}

func resetRecordAnimation() {
    self.myRecordPlayerBtn.imageView!.stopAnimating()
    self.myRecordPlayerBtn.isSelected = false
}

func recordPlay(_ sender: UIButton) {

    self.myRecordPlayerBtn.imageView?.startAnimating()

    let documentsDirectoryURL = try! FileManager().url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appendingPathComponent("\(chatroomId)/Record/")

    let fileName = message?.content.substring(from: 62)
    let fileURL = documentsDirectoryURL.appendingPathComponent(fileName!)
    if FileManager.default.fileExists(atPath: fileURL.path) {

        let asset = AVURLAsset(url: URL(fileURLWithPath: fileURL.path), options: nil)
        let audioDuration = asset.duration
        let audioDurationSeconds = CMTimeGetSeconds(audioDuration)
        self.elapsedTimeInSecond = Int(audioDurationSeconds)

        if audioPlayer?.isPlaying == true {

            audioPlayer?.stop()

            DispatchQueue.main.async {
                self.resetTimer(second: self.elapsedTimeInSecond)
                self.startTimer()
            }

        }

        updateTimeLabel()
        startTimer()

        audioPlayer = try? AVAudioPlayer(contentsOf: fileURL)
        audioPlayer?.delegate = self
        audioPlayer?.play()

    }else{
        //don't have file in local
        let recordUrl = URL(string: (message?.content)!)
        URLSession.shared.downloadTask(with: recordUrl!, completionHandler: { (location, response, error) in

            guard
                let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
                let mimeType = response?.mimeType, mimeType.hasPrefix("audio"),
                let location = location, error == nil
                else { return }
            do {
                try FileManager.default.moveItem(at: location, to: fileURL)

                let asset = AVURLAsset(url: URL(fileURLWithPath: fileURL.path), options: nil)
                let audioDuration = asset.duration
                let audioDurationSeconds = CMTimeGetSeconds(audioDuration)

                self.elapsedTimeInSecond = Int(audioDurationSeconds)

                DispatchQueue.main.async {
                    self.updateTimeLabel()
                    self.startTimer()
                }

                self.audioPlayer = try? AVAudioPlayer(contentsOf: fileURL)
                self.audioPlayer?.delegate = self
                self.audioPlayer?.play()

            } catch {
                print(error)
            }
        }).resume()
    }
}

func startTimer() {

    timer?.invalidate()
    timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { (timer) in
        self.elapsedTimeInSecond -= 1
        self.updateTimeLabel()
    })
}

func resetTimer(second:Int) {
    timer?.invalidate()
    elapsedTimeInSecond = second
    updateTimeLabel()
}

func updateTimeLabel() {

    let seconds = elapsedTimeInSecond % 60
    let minutes = (elapsedTimeInSecond/60) % 60

    mySecondLabel.isHidden = false
    mySecondLabel.text = String(format: "%02d:%02d", minutes,seconds)
}
}

extension TableViewCell:AVAudioPlayerDelegate {

func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {

    let documentsDirectoryURL = try! FileManager().url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appendingPathComponent("\(Id)/Record/")
    let fileName = message?.content.substring(from: 62)
    let fileURL = documentsDirectoryURL.appendingPathComponent(fileName!)

    if FileManager.default.fileExists(atPath: fileURL.path) {

        let asset = AVURLAsset(url: URL(fileURLWithPath: fileURL.path), options: nil)
        let audioDuration = asset.duration
        let audioDurationSeconds = CMTimeGetSeconds(audioDuration)

        DispatchQueue.main.async {
            self.resetTimer(second: Int(audioDurationSeconds))
            self.myRecordPlayerBtn.imageView!.stopAnimating()
            self.myRecordPlayerBtn.imageView?.image = #imageLiteral(resourceName: "img_myRocordDefault")
        }
    }
}
}

3 个答案:

答案 0 :(得分:1)

可能首先初始化以检查您的播放器是否正在播放

if audioPlayer != nil{
            if audioPlayer?.isPlaying == true {

                audioPlayer?.stop()

                DispatchQueue.main.async {
                    self.resetTimer(second: self.elapsedTimeInSecond)
                    self.startTimer()
                }

            }
        }

答案 1 :(得分:0)

如果您不想同时播放两个音轨,则应使用AVAudioPlayer的共享实例 它对性能更好,您可以在控制器中将实例定义为static var。它可以在每个单元格中访问。

答案 2 :(得分:0)

我开发了一个音乐palyer应用程序,我在MusicPlayManager中使用了一个共享实例:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="first">1</div>
<div id="second">2</div>
<div id="third">3</div>
<div id="fourth">4</div>

在viewController中,您可以使用class MusicPlayManager{ var player : AVAudioPlayer? static let sharedInstance = MusicPlayManager.init() private override init() { super.init() } // something else, such as palyNext, playPrevious methods }