I created a timer. When the timer ends it should play a complete sounds once. It is a soundfile that is about 5 seconds long.
But what happens is that when the timer ends, the sounds is playing over and over again and it only plays the first 2 seconds of the sound.
It happens on the simulator and a real device.
I have no idea why this is happening. I've been googling voor quite some time but I can't find a solution.
I tried to connect the sound to buttons, and the play and stop functions work fine. But even if I try to put the 'SoundManager.instance.stopSound()' into the stop button, it still doesn't stop playing the sound when I tap it when the timer ends.
Can someone tell me what I am doing wrong?
This is my code:
import SwiftUI
import AVKit
class SoundManager {
static let instance = SoundManager()
var player: AVAudioPlayer?
func playSound() {
guard let url = Bundle.main.url(forResource: "Tada", withExtension: ".mp3") else {return}
do {
player = try AVAudioPlayer(contentsOf: url)
player?.play()
} catch let error {
print("Error playing sound. \(error.localizedDescription)")
}
}
func stopSound() {
// Stop AVAudioPlayer
player?.stop()
}
}
struct TimerCountDown: View {
@State var countDownTimer = 30
@State var timerRunning = false
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
var body: some View {
VStack {
Text("\(countDownTimer)")
.onReceive(timer) { _ in
if countDownTimer > 0 && timerRunning {
countDownTimer -= 1
}
else if countDownTimer < 1 {
SoundManager.instance.playSound()
}
else {
timerRunning = false
}
}
.font(.system(size: 80, weight: .bold))
.opacity(0.80)
HStack (spacing: 30) {
Button("Start") {
timerRunning = true
}
.padding()
.background(.blue)
.foregroundColor(.white)
.cornerRadius(8)
Button("Stop") {
timerRunning = false
}
.padding()
.background(.blue)
.foregroundColor(.white)
.cornerRadius(8)
Button("Reset") {
countDownTimer = 30
}
.padding()
.background(.red)
.foregroundColor(.white)
.cornerRadius(8)
}
}
}
}
struct TimerCountDown_Previews: PreviewProvider {
static var previews: some View {
TimerCountDown()
}
}