Я бы предложил что-то вроде следующего:
class AudioModel: ObservableObject {
var audioPlayer: AVAudioPlayer?
@Published 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 audioModel = AudioModel()
var body: some View {
VStack {
ForEach(self.audioModel, id: .\self) { item in
Button(action:{
self.audioModel.current = item
}) {
Text(item)
}
}
}
}.onReceive(self.audioModel.$current) {
self.audioModel.stopSound()
self.audioModel.playSound()
}
}
Это не закончено, потому что я не смог проверить это, но я надеюсь, что это поможет для дальнейшего исследования.
@Published
аналогичнона @State
и дополнительно создает Publisher , поэтому при каждом обновлении будет выполняться вызов onReceive()
. Это достигается путем "наблюдения" объекта с помощью декоратора @ObservedObject
, который может применяться только к классу, соответствующему ObservableObject