For the following code, I am getting the following error. I don't know how to work around this. How can I call volumeCheck()
upon the button click?
struct ContentView: View {
var player = AVAudioPlayer()
var body: some View {
HStack {
Button(action: {
self.volumeCheck()
}) {
Text("Click to test chimes volume")
}
}
}
mutating func volumeCheck() {
guard let url = Bundle.main.url(
forResource: "chimes",
withExtension: "mp3"
) else { return }
do {
player = try AVAudioPlayer(contentsOf: url)
player.prepareToPlay()
player.volume = Float(self.sliderValue)
player.play()
} catch let error {
print(error.localizedDescription)
}
print("volume checked print")
}
}
The problem is that View
is a struct
and it's body
field is a computed property with a nonmutating getter. In your code it happens mutating method to be called in that nonmutating getter. So all you need to do is put your player to some kind of model:
class Model {
var player: AVPlayerPlayer()
}
struct ContentView: View {
var model = Model()
// player can be changed from anywhere
}
P.S. In some other cases you may want changes in your model be reflected in view so you'd have to add @ObservedObject just before model declaration.
Hope that helps
You are trying to set player to a new object in volumeCheck(). Set the player in your initialiser:
struct ContentView: View {
private var player: AVAudioPlayer?
public init() {
if let url = Bundle.main.url(forResource: "chimes",
withExtension: "mp3") {
self.player = try? AVAudioPlayer(contentsOf: url)
}
}
var body: some View {
HStack {
Button("Click to test chimes volume") {
self.volumeCheck()
} .disabled(player == nil)
}
}
private func volumeCheck() {
player?.prepareToPlay()
player?.volume = Float(self.sliderValue)
player?.play()
print("volume checked print")
}
}
Please note that you are using sliderValue in your code even though it is not defined anywhere.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With