Gadawg099
Gadawg099

Reputation: 127

Button with Timer.Interval is never-ending when button is pressed more than once before timer finishes

I've been working on this Truth, Dare or Drink app, and I have a button that when its pressed spins the card for 3 seconds then randomly picks a Truth, Dare or Drink card, with a random truth or dare to go along with it.

The only problem I'm having with it right now is that if you press the button more than once before the timer is finished, it will just keep going and never stop.

I'm trying to figure out a way to possibly make the button disabled until the timer is finished or something but I haven't been able to figure anything out. Does anyone have any ideas as to how I could fix this? I'm at a loss.

import SwiftUI
import CoreHaptics



class Colors{
    static var drinkGradient = [LinearGradient(gradient: Gradient(colors: [Color("drinkcard"), Color("drinkcard2"), Color("drinkcard")]), startPoint: .top, endPoint: .bottom)]
    static var truthGradient = [LinearGradient(gradient: Gradient(colors: [Color("truthcard"), Color("truthcard"), Color("truthcard")]), startPoint: .top, endPoint: .bottom)]
    static var dareGradient = [LinearGradient(gradient: Gradient(colors: [Color("darecard"), Color("darecard"), Color("darecard")]), startPoint: .top, endPoint: .bottom)]

}

class TruthorDares{
    static var truths = [String("Have you ever walked in on your parents doing it?"), String("Have you ever tasted a booger?"), String("Have you ever farted in an elevator?"), String("Have you ever peed yourself?"), String("What would be in your web history that you’d be embarrassed if someone saw?"),
    String("Who is the sexiest person in this room?"), String("What was the last thing you texted?"), String("What is the most illegal thing you have ever done?"),
    String("Would you rather lose your sex organs forever or gain 200 pounds?"), String("If someone offered you $1 million to break up with your girlfriend/boyfriend, would you do it?")]
    static var dares = [String("Let someone put lipstick on your lips."), String("Drink a glass of wine in less than 15 seconds."), String("Fill your mouth with water and try singing a song."), String("Striptease for thirty whole seconds."), String("Remove the socks of a person sitting next to you with your teeth."), String("Take off one item of clothing."), String("Wet your hair and apply shampoo, but don’t rinse it off."), String("Most the most embarrassing photo of yours, as FB profile picture."), String("Let someone sitting next to you spank you."), String("Call a random number and talk dirty to them.")]
    static var placeHolders = [String("")]
    static var drink = [String("Take a shot, or chug the rest of your drink!!")]

}

struct ContentView: View {

    // Picks foreground color based on which card is picked
    @State private var foregroundPicker = [1]
    // Picks which placeholder is going to be chosen based on which card is picked
    @State private var randText = [0]
    //Picks the random truth, dare or drink string from the TruthorDares class depending on which card is chosen
    @State private var placeHolder = [String("")]

    @State private var timer:Timer!
    //Picks which text to be shown on card
    @State private var text = [String("Truth"), String("Dare"), String("Truth"), String("Dare"), String("Truth"), String("Dare"), String("Drink!!")]
    @State private var foregrounds = [Color.white, Color.black]
    //Picks which text and card color are chosen
    @State private var number = [0]
    //Keeps time for the time interval in the spin button
    @State private var timeKeeper: Float = 0
    //For keeping the card spinning
    @State private var angle: Double = 0
    let generator = UINotificationFeedbackGenerator()
    //For choosing the color of the card depending on which text is chosen
    @State var backgrounds = [Colors.truthGradient[0], Colors.dareGradient[0], Colors.truthGradient[0], Colors.dareGradient[0], Colors.truthGradient[0], Colors.dareGradient[0], Colors.drinkGradient[0]]




    var body: some View {

        ZStack{
            //Background
            Rectangle()
                .foregroundColor(Color("background"))
                .edgesIgnoringSafeArea(.all)
            VStack{
                HStack {
                    //Top banner
                    Text("Truth, Dare or Drink")
                        .shadow(radius: 10)
                        .padding(.top, 20)
                        .foregroundColor(.white)
                        .font(.system(.largeTitle, design: .rounded) )
                        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 100)
                        .background(Color("banner"))
                        .edgesIgnoringSafeArea(.top)
                        .shadow(radius: 15)
                }

                //Where the truth or dare will go depending on which one is picked
                Text(String(placeHolder[0]))
                    .frame(width: 350, height: 200)
                    .foregroundColor(.white)
                    .font(.system(.headline, design: .rounded))

                Spacer()
                //The truth, dare or drink random card
                Text(text[number[0]])
                    .font(.system(.largeTitle, design: .rounded))
                    .foregroundColor(foregrounds[foregroundPicker[0]])
                    .frame(width: 250, height: 250)
                    .background(backgrounds[number[0]])
                    .clipShape(RoundedRectangle(cornerRadius: 15, style: .continuous))
                    .shadow(radius: 10)
                    .rotationEffect(.degrees(angle))
                    .animation(.easeIn)

                Spacer()

                Button(action: {
                    self.timer = Timer.scheduledTimer(withTimeInterval: 0.10, repeats: true, block: {_ in

                        self.timeKeeper += 0.10
                        let impactHeavy = UIImpactFeedbackGenerator(style: .heavy)
                        impactHeavy.impactOccurred()
                        if self.timeKeeper < 3{
                            if self.number[0] == self.text.count - 1{
                                self.number[0] = 0
                                self.number[0] += 1
                                self.angle += 360
                            }
                            else{
                                self.number[0] += 1
                                self.angle += 360
                            }
                        }
                        else{
                            self.number[0] = Int.random(in:
                                0...self.text.count - 1)
                            self.angle += 360
                            self.timeKeeper = 0
                            if self.number[0] == 0 || self.number[0] == 2 || self.number[0] == 4{
                                self.placeHolder[0] = TruthorDares.truths.randomElement()!
                                self.foregroundPicker[0] = Int(1)
                            }
                            else if self.number[0] == 1 || self.number[0] == 3 || self.number[0] == 5{
                                self.placeHolder[0] = TruthorDares.dares.randomElement()!
                                self.foregroundPicker[0] = Int(0)
                            }
                            else{
                                self.placeHolder[0] = TruthorDares.drink.randomElement()!
                                self.foregroundPicker[0] = Int(1)
                            }
                            self.timer.invalidate()
                        }
                    })
                }) {
                    Text("Spin")
                        .font(.system(.title, design: .rounded))
                        .foregroundColor(.white)
                        .frame(width: 250, height: 50)
                        .background(Color("button"))
                        .clipShape(RoundedRectangle(cornerRadius: 15, style: .continuous))
                        .shadow(radius: 15)

                }
                Spacer()
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Upvotes: 0

Views: 115

Answers (2)

I would just have:

@State private var isBusy = false

and use it in the button:

Button(action: {
  if !self.isBusy {
  self.isBusy = true
  // ... your code here
}

and just before the timer is done:

self.isBusy = false

Upvotes: 0

jbiser361
jbiser361

Reputation: 987

You can simply do an if statement that checks to see if the timer is done, if so re-enable the button. and if the timer is restarted doable the button. Make sense?

to disable a button in Swift do: buttonName.isEnabled = false

then to re-enable it just switch the false to a true

Upvotes: 1

Related Questions