Как запустить функцию в течение l oop последовательно - PullRequest
0 голосов
/ 18 марта 2020

У меня есть набор кнопок в виде стека. Каждая кнопка при нажатии воспроизводит другой звук. У меня есть отдельная кнопка (кнопка l oop), которая при нажатии вызывает функцию loopButtonPressed. Моя цель состоит в том, чтобы при нажатии этой кнопки l oop она проходила через l oop через подпредставления, являющиеся кнопками в этом виде стека, и последовательно воспроизводила каждый из звуков в порядке, используя функцию 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)
        }
    }

Ответы [ 2 ]

0 голосов
/ 18 марта 2020

Попытка 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()
}
0 голосов
/ 18 марта 2020
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 {

и вместо цикла добавьте каждой кнопке тег и начните с первого тега sat 100. Затем, когда обратный вызов, полученный для игрока, закончил играть, воспроизведите следующий файл с новым тегом icremented скажем 101

...