Swift和AVFoundation:在制作标签动画时播放音频

时间:2017-10-30 20:32:14

标签: ios swift avfoundation uiviewanimation

我有一个应用程序,我正在添加声音。它有一个键盘,当用户点击一个按钮时,该数字会动画显示用户他们的印刷机经过。

但是,由于两者都发生在主线程上,下面添加以下代码,play()函数会导致动画略有延迟。如果用户等待约2秒钟并再次点击键盘编号,他们会再次看到延迟。因此,只要他们击中2秒以下的键盘数字,他们就不会看到另一个滞后。

我尝试将下面的代码包装在DispatchQueue.main.async {}块中但没有运气。

if let sound = CashSound(rawValue: "buttonPressMelody\(count)"),
    let url = Bundle.main.url(forResource: sound.rawValue, withExtension: sound.fileType) {
    self.audioPlayer = try? AVAudioPlayer(contentsOf: url)
    self.audioPlayer?.prepareToPlay()

    self.audioPlayer?.play()
}

如何播放此音频并让动画在没有它们干扰的情况下运行并且音频与媒体一致?

由于

1 个答案:

答案 0 :(得分:0)

我在SwiftUI应用程序中遇到了一个类似的问题,在我的情况下,解决方案是正确的资源加载/ AVAudioPlayer初始化和准备。

我使用以下功能从磁盘加载音频(受Apple地标SwiftUI教程的ImageStore类启发)


final class AudioStore {
    typealias Resources = [String:AVAudioPlayer]
    fileprivate var audios: Resources = [:]

    static var shared = AudioStore()


    func audio(with name: String) -> AVAudioPlayer {
        let index = guaranteeAudio(for: name)

        return audios.values[index]
    }

    static func loadAudio(with name: String) -> AVAudioPlayer {
        guard let url = Bundle.main.url(forResource: name, withExtension: "mp3") else { fatalError("Couldn't find audio \(name).mp3 in main bundle.") }
        do { return try AVAudioPlayer(contentsOf: url) }
        catch { fatalError("Couldn't load audio \(name).mp3 from main bundle.") }
    }
    fileprivate func guaranteeAudio(for name: String) -> Resources.Index {
        if let index = audios.index(forKey: name) { return index }

        audios[name] = AudioStore.loadAudio(with: name)
        return audios.index(forKey: name)!
    }
}

  1. 在视图的初始化中,我通过使用正确的资源名称调用audio(with :)来初始化播放器的实例。

  2. 在onAppear()中,我使用适当的可选展开功能在视图已初始化的播放器上调用prepareToPlay(),最后

  3. 手势触发时我会播放音频。

此外,就我而言,我需要将实际播放延迟约0.3秒,为此,我将其分派到全局队列中。我要强调的是,即使没有将音频分发到后台队列,带有音频播放的动画也很流畅,因此我得出结论,关键在于正确的初始化和准备工作。但是,要延迟播放,您只能使用后台线程,否则会出现延迟。

DispatchQueue.global(qos: .userInitiated).asyncAfter(deadline: .now() + 0.3) {
   ///your audio.play() analog here
}

希望能帮助一些灵魂。