How do I get a button to be receptive to a tap while a function is running?
I am coding in Swift playgrounds on a blank page on my ipad.
To explain further: I am coding a simple drum machine. I have a stop and a start button. When I tap the start button a function called loop1 is called. A drum loop continues indefinitely in a "while" loop untill a boolean variable called "playing" is changed to false. So a tap of the stop button simply changes my "playing" variable to false and should stop the function , and hence the drum loop.
Unfortunately once I start my loop going the stop button doesn't react to a tap. I guess Swift is tied up in running the function.
Below I have extracted a simplified version of my code with just the buttons. I have ommitted Hstacks etc. I just copied the code and pasted it below. I don't know how to put the code in the nice format used on this site. Also I don't know how to include the (legal) drum file i used. This code works if it is pasted into a blank playground page.
Anyway I will paste the code below.
import SwiftUI
import PlaygroundSupport
import AVFoundation
PlaygroundPage.current.wantsFullScreenLiveView = true
// variable declarations
var playing:Bool = true
var t2: Double = 1
var t1: Double = 1
var BPM:Double = 100
let screenWidth = UIScreen.main.bounds.width
let screenHeight = UIScreen.main.bounds.height
// end of variable declarations
struct DrumMachine: View{
@State var SnarePlayer: AVAudioPlayer?
var body: some View{
Button(action: {// start button
loop1()
}) {
Image(systemName: "play.circle")
.foregroundColor(.green)
}
.frame(width: 0.2*screenHeight, height: 0.2*screenHeight)
.scaleEffect(5)
.background(Color.clear)
//finish of play button
Button(action: {// stop button
playing = false
}) {
Image(systemName: "stop.circle")
.foregroundColor(.red)
.frame(width: 0.2*screenHeight, height: 0.2*screenHeight)
.scaleEffect(5)
.background(Color.clear)
.disabled(false)
}
.onAppear(){Snare(vol: 0)}
}//end of some view
func Snare(vol: Float){
if let SnareURL = Bundle.main.url(forResource: "Snare Drum", withExtension: "mp3") {
do {
try self.SnarePlayer = AVAudioPlayer(contentsOf: SnareURL) /// make the audio player
SnarePlayer?.volume = vol
self.SnarePlayer?.play() /// start playing
} catch {
print("Couldn't play audio. Error: \(error)")
}
}
}//end of snare function
func loop1() {
playing = true
while playing == true{
for a in 1...4{
t1 = CFAbsoluteTimeGetCurrent()
Snare(vol: 2)
t2 = CFAbsoluteTimeGetCurrent()
while t2 - t1 < (1) {
t2 = CFAbsoluteTimeGetCurrent()
}
}
}
}
}//end of struct
PlaygroundPage.current.setLiveView(DrumMachine())
PlaygroundPage.current.wantsFullScreenLiveView = true
It would be good if some kind soul could help me sort this one.