|
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{
}//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. |
|
|
|
Thanks I tried changing playing to an @variable. My code still worked but it made no difference. I still couldn't press my stop button the so I couldn't pass my boolean variable, playing and stop the loop. I wonder if Swift doesn't check the ui while the while loop is running. |
|
That loop code is running on the main loop and so just continues in a loop. Also the Snare is loading an AVPlayer into memory everytime. All of that is expensive, so the main thread is blocked and you cant hit the stop button. I dont really think that code is very efficient anyway, but I am no expert in AVAudioPlayer. But make AVAudioPlayer a global for sure. And move the loop to another thread. |
|
Thanks for the reply The only way I could find to play an mp3 is to recreate the avaudioplayer each time. This is quite a process and a few of them are needed to make a drum sound. as for threading that might be beyond me. I will investigate. |
|
Thanks for the reply The only way I could find to play an mp3 is to recreate the avaudioplayer each time. This is quite a process and a few of them are needed to make a drum sound. as for threading that might be beyond me. I will investigate. |
|
Thanks for your help eoinnorris, and NigelGee. To make the function play in a background thread you call your function (Kick_Snare in this case.) inside a DispatchQueue.global as shown below. This thread runs in parallel with the main thread and the buttons are now pressable.
or name a dispatch queue like this:
then call the function like this:
Also you don't have to create the avaudio players every time. They are played like this. (from another question I posted)
|
SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.
Sponsor Hacking with Swift and reach the world's largest Swift community!
This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.
All interactions here are governed by our code of conduct.
Link copied to your pasteboard.