2017-08-07 3 views
1

Ich habe eine Tabellenansicht und mehrere Zellen in TableView.
Jede Zelle hat einen AVAudioPlayer
Und ich habe ein Problem.
Ich weiß nicht, wie man den AVAudioPlayer verwaltet.
Wenn ich zuerst den AVAudioPlayer spiele und dann den zweiten AVAudioPlayer, wird der Ton überlappen.
Wie Stop ersten AVAudioPlayer in meiner benutzerdefinierten Zelle, und spielen Sie den zweiten AVAudioPlayer?
Danke.
Wie wird der AVAudioPlayer in jeder Tabellenansicht verwaltet?

Dies ist meine maßgeschneiderte Zelle:

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") 
     } 
    } 
} 
} 

Antwort

0

Wahrscheinlich initialisieren zunächst zu überprüfen, ob Ihr Player

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

       audioPlayer?.stop() 

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

      } 
     } 
+0

Aber wie Manager unterschiedliche Zelle Audioplayer und es machen können halt? Dies ist Arbeit in einer Zelle und wiederhole den gleichen Klick. Wenn ich auf eine andere Zelle klicke, funktioniert das nicht. Der Sound wird sich überlappen. –

+0

Gibt es einen bestimmten Grund für die AudioPlayer Dinge innerhalb der TableViewCell Klasse? desto besser wäre es, einen audioPlayer im View-Controller zu initialisieren und einen Verweis auf die Tabellenansichtszelle zu übergeben, wenn Sie diesen Ansatz verwenden möchten. Der andere Weg wäre, dies komplett aus der tableViewCell herauszunehmen und es zur Steuerung zu bringen. Dort haben Sie nur eine audioPlayer-Instanz, die Sie anhalten/abspielen können, ohne das Problem der Überlappung des Klangs zu haben. –

0

spielt Wenn Sie wollen Zeit nicht spielen zwei Audiospur auf der gleichen , sollten Sie eine gemeinsame Instanz von AVAudioPlayer verwenden Es wird besser für Leistungen und Sie können die Instanz als static var in Ihrem Controller definieren. Es wird in jeder Zelle zugänglich sein.

0

Ich habe eine Musik palyer Anwendung entwickelt, und ich eine gemeinsame Instanz im MusicPlayManager:

class MusicPlayManager{ 

    var player : AVAudioPlayer? 

    static let sharedInstance = MusicPlayManager.init() 

    private override init() { 
     super.init() 

    } 

// something else, such as palyNext, playPrevious methods 
} 

In Ihrem Viewcontroller, Sie MusicPlayManager.sharedInstance.player

Verwandte Themen