Passing a variable to a function

I am reposting this question with my code included.

I don’t know if I am putting this question in the right place. I am not a developer but am coding in swift / SwiftUI more as a hobby, on an iPad using Swift Playgrounds.

I am coding a basic drum machine and trying to get start stop buttons functioning. My loops are in functions. I tap the start button and the loop starts playing as expected. Then I was hoping to set my Boolean variable - “playing” to false with the stop button, and stop the while loop in my function called loop1.

However the stop button can’t be tapped so I can change the variable. The start button takes on a pressed appearance and can’t be tapped as either.

Below is a shorter version of my code.

import SwiftUI

import PlaygroundSupport

import AVFoundation

PlaygroundPage.current.wantsFullScreenLiveView = true

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

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.2screenHeight, height: 0.2screenHeight)

        .scaleEffect(5)

        .background(Color.clear)

        //finish of play button

        Button(action: {// stop button

            playing = false

        }) {

            Image(systemName: "stop.circle")

                .foregroundColor(.red)

                .frame(width: 0.2screenHeight, height: 0.2screenHeight)

                .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() {

        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

Answered by Congokjt in 679121022
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 buttonloop1()

        }) {

            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() {

        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




You should better use Code Block when you show some code. If you can edit your post, please try.

thanks for the reply. I don’t know what Code Block is but I will try and find out.

This code is in Code Block form as far as I know. if you pasted my code into a blank playground on an iPad all the parentheses containing the blocks would be linked. I suppose I could annotate the start and end of every block but it would make it harder to read. I couldn’t find a way of copying an actual playground to the forum.

OOPer is asking you to reformat your post so that it’s easier to read. Specifically, if you include your code snippets in triple backticks, DevForums will render it as a code block. For example:

#include <stdio.h>

int main(int argc, char ** argv) {
    printf("Hello Cruel World!\n");
}

The DevForums editor has a button that inserts the triple backticks for you (see the image below). It’s tool tip says Code Block, so folks call it the “Code Block button” and call the resulting structure a “Code Block”.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Accepted Answer
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 buttonloop1()

        }) {

            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() {

        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




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: {

            loop1()// start buttonloop1()

        }) {

            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() {

        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


I found the answer to this question on another forum. My apologies I worded it badly and didn’t know how to edit the post or put my code in block form so it was long winded. It turns out the answer is to call your function on a background thread like this to run a function called Kick_Snare in this case.

DispatchQueue.global(qos: .userInitiated).async { Kick_Snare()}

The loop then runs in parallel to the user interface and the buttons are available.

Passing a variable to a function
 
 
Q