UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

Changing text when button is pressed

Forums > SwiftUI

I'm a complete beginner, I am following the 100 days of SwiftUI but as someone with zero experience it's slow going. I am trying to put what I have learned into practice which helps me to remember at least parts of what I am learning.

But I am stuck on what I feel should be a pretty simple task. I have a function that makes a random paragraph out of some arrays. It generates the paragraph on load, but I wanted a button to create a new paragraph when pressed. Below is my code, could someone point me in the right direction?


import SwiftUI

struct ContentView: View {

    func timeToDie() -> String {
        let moodDie = ["happy", "sad", "quite pleased",]
        let dieDate = ["in a month", "in about a week", "next Tuesday", "almost a year to the day"]
        let howDie = ["be eaten by cats", "get stuck in the washing machine", "fall into a puddle"]
        let doingDie = ["digging for bones", "mixing a drink", "fishing for hats", "waiting for a bus"]
        let whereDie = ["a side street in Paris", "the Treaty Center", "the Bell Road"]
        var result = ""

        result = ("I'm \(moodDie.randomElement() ?? "") to tell you that \(dieDate.randomElement() ?? "") you will \(howDie.randomElement() ?? "") while \(doingDie.randomElement() ?? "") in \(whereDie.randomElement() ?? "").")

        return result

    }

    var body: some View {
        ZStack {
            Color.black
                .ignoresSafeArea()
            VStack {
                Spacer()

                Button(action: {timeToDie()
                }, label: {
                    Text("When will it happpen?")
                        .foregroundColor(Color.white)
                        .multilineTextAlignment(.center)
                        .font(Font.headline)
                        .padding()
                })

                Text(timeToDie())
                    .foregroundColor(Color.white)
                    .multilineTextAlignment(.center)
                    .font(Font.headline)
                    .padding()

                Spacer()

  }

        }
    }
}

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

1      

can you please try below code - in SwiftUI , the button click will not change any thing , our mind thinks like it should , but here the compiler want a source of truth to change , which is a property wrapper in your case @State private var changeQuestion = false

then i toggle it on button click, so it become true, then inside body i check it like so if changeQuestion { , however now there is a catch again , we are stuck with true value , how do we change it again, so i just use an else block where your function already calls a random para while you are also clicking on button turning it to true again, doing so also toggles my if changeQuestion {section to true so now it runs , so on and so forth

So in short - first click , becomes true, then on second click become false , but you still get a new para as you are now calling your random function, on third click becomes true ,so function is called again and the cycle continues

struct ContentView: View {

    func timeToDie() -> String {
            let moodDie = ["happy", "sad", "quite pleased",]
            let dieDate = ["in a month", "in about a week", "next Tuesday", "almost a year to the day"]
            let howDie = ["be eaten by cats", "get stuck in the washing machine", "fall into a puddle"]
            let doingDie = ["digging for bones", "mixing a drink", "fishing for hats", "waiting for a bus"]
            let whereDie = ["a side street in Paris", "the Treaty Center", "the Bell Road"]
            var result = ""

            result = ("I'm \(moodDie.randomElement() ?? "") to tell you that \(dieDate.randomElement() ?? "") you will \(howDie.randomElement() ?? "") while \(doingDie.randomElement() ?? "") in \(whereDie.randomElement() ?? "").")

            return result

        }

   @State private var changeQuestion = false
    var body: some View {
        ZStack {
                    Color.black
                        .ignoresSafeArea()
                    VStack {
                        Spacer()

                        Button {
                            changeQuestion.toggle()
                        } label: {
                            Text("When will it happpen?")
                                                            .foregroundColor(Color.white)
                                                            .multilineTextAlignment(.center)
                                                            .font(Font.headline)
                                                            .padding()
                        }
                        if changeQuestion {
                            Text(timeToDie())
                                .foregroundColor(Color.white)
                                .multilineTextAlignment(.center)
                                .font(Font.headline)
                                .padding()
                        } else {
                            Text(timeToDie())
                                .foregroundColor(Color.white)
                                .multilineTextAlignment(.center)
                                .font(Font.headline)
                                .padding()
                        }

                        Spacer()

          }

                }

        }

}

1      

As @AmritShirvastava has indicated, you need an @State for your view. If you want to keep the timeToDie() action, then you have to create a variable for the string.

struct ContentView: View {

    @State private var timeIsNigh = "Sooner or later"

    func timeToDie() {
        let moodDie = ["happy", "sad", "quite pleased",]
        let dieDate = ["in a month", "in about a week", "next Tuesday", "almost a year to the day"]
        let howDie = ["be eaten by cats", "get stuck in the washing machine", "fall into a puddle"]
        let doingDie = ["digging for bones", "mixing a drink", "fishing for hats", "waiting for a bus"]
        let whereDie = ["a side street in Paris", "the Treaty Center", "the Bell Road"]
        // var result = ""

        timeIsNigh = ("I'm \(moodDie.randomElement() ?? "") to tell you that \(dieDate.randomElement() ?? "") you will \(howDie.randomElement() ?? "") while \(doingDie.randomElement() ?? "") in \(whereDie.randomElement() ?? "").")

        // return result
    }

    var body : some View {

        ZStack {
            Color.black
                .ignoresSafeArea()
            VStack {
                Spacer()

                Button(action: {timeToDie()
                }, label: {
                    Text("When will it happpen?")
                        .foregroundColor(Color.white)
                        .multilineTextAlignment(.center)
                        .font(Font.headline)
                        .padding()
                })

                Text(timeIsNigh)
                    .foregroundColor(Color.red)
                    .multilineTextAlignment(.center)
                    .font(Font.headline)
                    .padding()

                Spacer()

            }
        }
    }
}

1      

Thank you, I'm going to resist the tempation to copy and paste but will look at these and try and learn from them!

1      

Hacking with Swift is sponsored by RevenueCat

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.

Learn more here

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

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.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.