带有 SwiftUI 的播放/停止按钮

问题描述 投票:0回答:2

我正在开发一个可以播放列表中显示的音频文件的应用程序。

音频文件1
音频文件2
...
音频文件10

我有使用以下代码的音频。

var audioPlayer: AVAudioPlayer?


func playSound1() {

    let path = Bundle.main.path(forResource: "audiofile1.mp3", ofType:nil)!
    let url = URL(fileURLWithPath: path)

    do {
        audioPlayer = try AVAudioPlayer(contentsOf: url)
        audioPlayer?.play()
    } catch {
        print("Could not find file")

    }
}


struct ContentView: View {
    var body: some View {
        Button(action:{ playSound1()}) {
            Text("Audio File 1") }
    }
}

我正在寻找解决方案,当第二次点击音频文件 1 时,它将停止播放音频文件 1。此外,如果音频文件 1 正在播放,并且在音频文件 2 上点击一下,则会停止播放音频文件 1 并播放音频文件 2。希望所有 10 个音频文件都发生这种情况。

ios swift audio swiftui
2个回答
3
投票

我建议如下:



class AudioModel: ObservableObject {
    var audioPlayer: AVAudioPlayer?

    @Published var current: String = ""

    var audioFiles = ["audiofile1.mp3", "audiofile2.mp3", "audiofile3.mp3"]

    func playSound() {

        let path = Bundle.main.path(forResource: self.current, ofType:nil)!
        let url = URL(fileURLWithPath: path)

        do {
            audioPlayer = try AVAudioPlayer(contentsOf: url)
            audioPlayer?.play()
        } catch {
            print("Could not find file")

        }
    }

    func stopSound() {
        // Stop AVAudioPlayer
        // audioPlayer.stop() ???
    }
}




struct ContentView: View {

    @ObservedObject var audioModel = AudioModel()

    var body: some View {
        VStack {
            ForEach(self.audioModel.audioFiles, id: \.self) { item in
                Button(action:{ 
                        self.audioModel.current = item
                    }) {
                        Text(item) 
                    }
                }
            }
        }.onReceive(self.audioModel.$current) {_ in
            self.audioModel.stopSound()
            self.audioModel.playSound()
        }
    }

尚未完成,因为我无法测试它,但我希望这有助于进一步调查。

@Published
@State
类似,还创建了一个 Publisher,因此每当更新时,都会进行
onReceive()
调用。这是通过使用
@ObservedObject
装饰器“观察”对象来实现的,该装饰器只能应用于符合
ObservableObject

的类

0
投票
import AVFoundation

// Audio Model
final class AudioModel: ObservableObject {

    @Published var current = ""

    static let shared = AudioModel()
    private init() {}

    var audioPlayer: AVAudioPlayer?

    var audioFiles = ["audiofile1.mp3", "audiofile2.mp3", "audiofile3.mp3"]

    func playSound() {
    
        let path = Bundle.main.path(forResource: current, ofType: nil)!
        let url = URL(fileURLWithPath: path)
    
            do {
                audioPlayer = try AVAudioPlayer(contentsOf: url)
                audioPlayer?.play()
            } catch {
                print("Could not find file")

            }
    }

    func stopSound() {
        // Stop AVAudioPlayer
        audioPlayer?.stop()
    }
}

    
    
    
// Usage example

struct ContentView: View {
    
    @StateObject var audioModel = AudioModel.shared

    var body: some View {
        VStack {
            ForEach(audioModel.audioFiles, id: \.self) { item in
                Button {
                    play(item)
                } label: {
                    Text(item)
                }
            }
        }
    }

    private func play(_ track: String) {
        audioModel.current = track
        audioModel.stopSound()
        audioModel.playSound()

    }
}
© www.soinside.com 2019 - 2024. All rights reserved.