0

我在堆栈视图中有一组按钮。按下每个按钮都会播放不同的声音。我有一个单独的按钮(循环按钮),按下时会调用该loopButtonPressed函数。我的目标是,当按下此循环按钮时,它将循环通过作为此堆栈视图中按钮的子视图,并按顺序使用该soundButtonPressed功能按顺序播放每个声音。我看到了一个我在下面使用的方法run()将每个连续函数设置为在给定时间后运行的函数。虽然这种工作方式它不是一个很好的解决方案,因为声音文件的长度不同。我在想可能有一种方法可以使用调度组来做到这一点,但我并不完全理解。如果我去掉运行功能,它只会播放堆栈视图中最后一个按钮的声音。我也在使用 AVFoundation 来播放 wav 文件。我感谢任何建议或指导,谢谢。

    func run(after seconds: Int, completion: @escaping () -> Void) {
        let deadline = DispatchTime.now() + .milliseconds(seconds)
        DispatchQueue.main.asyncAfter(deadline: deadline) {
            completion()
        }
    }

    @objc func loopButtonPressed(_ sender: UIButton) {
        var i = 1
        for case let button as UIButton in self.colorBubblesStackView.subviews {
            run(after: 800*i) {
                self.soundButtonPressed(sender: button)
            }
            i += 1
        }
    }

我的 soundButtonPressed 函数只是一个 switch 语句,其中每个案例都playSound()使用正确的声音文件名调用该函数。这是 playSound 函数:

func playSound(_ soundFileName: String) {
        guard let url = Bundle.main.url(forResource: soundFileName, withExtension: "wav") else { return }

        do {
            try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
            try AVAudioSession.sharedInstance().setActive(true)

            player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileType.wav.rawValue)

            guard let player = player else { return }

            player.play()

        } catch let error {
            print(error.localizedDescription)
        }
    }
4

2 回答 2

0

尝试AVQueuePlayer

用于按顺序播放多个项目的玩家。

@objc func loopButtonPressed(_ sender: UIButton) {
    let allUrls = allSongs.compactMap { Bundle.main.url(forResource: $0, withExtension: "wav") }
    let items = allUrls.map { AVPlayerItem(url: $0) }
    let queuePlayer = AVQueuePlayer(items: items)
    queuePlayer.play()
}
于 2020-03-18T05:30:25.813 回答
0
func playSound(name: String ) {
        guard let url = Bundle.main.url(forResource: name, withExtension: "mp3") else {
            print("url not found")
            return
        }

        do {
            /// this codes for making this app ready to takeover the device audio
            try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
            try AVAudioSession.sharedInstance().setActive(true)

            /// change fileTypeHint according to the type of your audio file (you can omit this)
            player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileTypeMPEGLayer3)

            player?.delegate = self

            // no need for prepareToPlay because prepareToPlay is happen automatically when calling play()
            player!.play()
        } catch let error as NSError {
            print("error: \(error.localizedDescription)")
        }
    }

    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
        print("finished")//It is working now! printed "finished"!
    }

确认协议

class ViewController: UIViewController,AVAudioPlayerDelegate {

而不是循环添加每个按钮一个标签并从第一个标签开始 100 。然后,当为播放器获得的回调完成播放时,播放下一个带有新添加标签的文件,例如 101

于 2020-03-18T04:50:59.547 回答