因此,我有一个名为“音频设置”的类,如下所示:

class audioSettings: ObservableObject {

    var audioPlayer: AVAudioPlayer?
    var playing = false
    var playValue: TimeInterval = 0.0
    var playerDuration: TimeInterval = 146
    var timer = Timer.publish(every: 0.1, on: .main, in: .common).autoconnect()


    func playSound(sound: String, type: String) {
        if let path = Bundle.main.path(forResource: sound, ofType: type) {
            do {
                if playing == false {
                    if (audioPlayer == nil) {


                        audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: path))
                        audioPlayer?.prepareToPlay()

                        audioPlayer?.play()
                        playing = true
                    }

                }
                if playing == false {

                    audioPlayer?.play()
                    playing = true
                }


            } catch {
                print("Could not find and play the sound file.")
            }
        }

    }



    func stopSound() {
        //   if playing == true {
        audioPlayer?.stop()
        audioPlayer = nil
        playing = false
        playValue = 0.0


        //   }
    }

    func pauseSound() {
        if playing == true {
            audioPlayer?.pause()
            playing = false


        }
    }


    func changeSliderValue() {
        if playing == true {
            pauseSound()
            audioPlayer?.currentTime = playValue

        }

        if playing == false {


            audioPlayer?.play()
            playing = true
        }
    }
}
当我在视图中实现代码时,播放文件就成功了。我成功停止了它,并且成功移动了滑块并在音频中获得了新的位置。
我正在努力的工作是使滑块在音频播放时实时更新。如果我点击播放,则在我暂停之前,滑块将不起作用。此时它将移动到正确的位置。
这是视图代码:
struct myExperienceFearChunk: View {


    @ObservedObject var audiosettings = audioSettings()


    var body: some View {


            HStack {
                Button(action: {
                    if (self.playButton == Image(systemName: "play.circle")) {
                        print("All Done")
                        self.audiosettings.playSound(sound: "audio file", type: "mp3")
                        self.audiosettings.timer = Timer.publish(every: 0.1, on: .main, in: .common).autoconnect()
                        self.playButton = Image(systemName: "pause.circle")

                    } else {

                        self.audiosettings.pauseSound()
                        self.playButton = Image(systemName: "play.circle")


                    }


                }) {
                    self.playButton
                        .foregroundColor(Color.white)
                        .font(.system(size: 44))
                }
                Button(action: {
                    print("All Done")
                    self.audiosettings.stopSound()
                    self.playButton = Image(systemName: "play.circle")
                    self.audiosettings.playValue = 0.0

                }) {
                    self.stopButton
                        .foregroundColor(Color.white)
                        .font(.system(size: 44))

                }
            }
            Slider(value: $audiosettings.playValue, in: TimeInterval(0.0)...audiosettings.playerDuration, onEditingChanged: { _ in
                self.audiosettings.changeSliderValue()
            })
                .onReceive(audiosettings.timer) { _ in

                    if self.audiosettings.playing {
                        if let currentTime = self.audiosettings.audioPlayer?.currentTime {
                            self.audiosettings.playValue = currentTime

                            if currentTime == TimeInterval(0.0) {
                                self.audiosettings.playing = false
                            }
                        }

                    }
                    else {
                        self.audiosettings.playing = false
                        self.audiosettings.timer.upstream.connect().cancel()
                    }
            }
        }
    }
}
我知道.onReceive是从我按下暂停时开始更新滑块的位置,因为没有它,除非拖动它,否则滑块不会更新。
关于如何在音频播放时更新滑块的任何想法,请设置playValue。
谢谢。

最佳答案

这是固定代码。经过Xcode 11.4 / iOS 13.4测试
修复的主要内容是发布@Published var playValue,以便在观察到对象时有机会通知audioSettings的变化,从而更新Slider…其他是次要的。

class audioSettings: ObservableObject {

    var audioPlayer: AVAudioPlayer?
    var playing = false
    @Published var playValue: TimeInterval = 0.0
    var playerDuration: TimeInterval = 146
    var timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()


    func playSound(sound: String, type: String) {
        if let path = Bundle.main.path(forResource: sound, ofType: type) {
            do {
                if playing == false {
                    if (audioPlayer == nil) {


                        audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: path))
                        audioPlayer?.prepareToPlay()

                        audioPlayer?.play()
                        playing = true
                    }

                }
                if playing == false {

                    audioPlayer?.play()
                    playing = true
                }


            } catch {
                print("Could not find and play the sound file.")
            }
        }

    }

    func stopSound() {
        //   if playing == true {
        audioPlayer?.stop()
        audioPlayer = nil
        playing = false
        playValue = 0.0
        //   }
    }

    func pauseSound() {
        if playing == true {
            audioPlayer?.pause()
            playing = false
        }
    }

    func changeSliderValue() {
        if playing == true {
            pauseSound()
            audioPlayer?.currentTime = playValue

        }

        if playing == false {
            audioPlayer?.play()
            playing = true
        }
    }
}

struct myExperienceFearChunk: View {
    @ObservedObject var audiosettings = audioSettings()
    @State private var playButton: Image = Image(systemName: "play.circle")

    var body: some View {

        VStack {
        HStack {
            Button(action: {
                if (self.playButton == Image(systemName: "play.circle")) {
                    print("All Done")
                    self.audiosettings.playSound(sound: "filename", type: "wav")
                    self.audiosettings.timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
                    self.playButton = Image(systemName: "pause.circle")

                } else {

                    self.audiosettings.pauseSound()
                    self.playButton = Image(systemName: "play.circle")
                }
            }) {
                self.playButton
                    .foregroundColor(Color.white)
                    .font(.system(size: 44))
            }
            Button(action: {
                print("All Done")
                self.audiosettings.stopSound()
                self.playButton = Image(systemName: "play.circle")
                self.audiosettings.playValue = 0.0

            }) {
                Image(systemName: "stop.circle")
                    .foregroundColor(Color.white)
                    .font(.system(size: 44))
            }
        }
        Slider(value: $audiosettings.playValue, in: TimeInterval(0.0)...audiosettings.playerDuration, onEditingChanged: { _ in
            self.audiosettings.changeSliderValue()
        })
            .onReceive(audiosettings.timer) { _ in

                if self.audiosettings.playing {
                    if let currentTime = self.audiosettings.audioPlayer?.currentTime {
                        self.audiosettings.playValue = currentTime

                        if currentTime == TimeInterval(0.0) {
                            self.audiosettings.playing = false
                        }
                    }

                }
                else {
                    self.audiosettings.playing = false
                    self.audiosettings.timer.upstream.connect().cancel()
                }
            }
        }
    }
}

关于ios - 实时更新滑块值AVAudioPlayer SwiftUI,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/63324235/

10-14 21:01