rjbcg81
rjbcg81

Reputation: 61

SwiftUI - How to update a value through a function (with a slider)?

I am new to programming and SwiftUI and I am trying to get my head around this problem:

I have created a simple slider:

Slider(value: $sliderValue, in: 0...100, step: 1)
            .padding(8)
            .overlay(
                Capsule()
                    .stroke(Color.purple, style: StrokeStyle(lineWidth: 5))
        )

I can display the value in a TextView:

Text("\(sliderValue)")

Now what I want to do is create another TextView, which displays the Slider Value with a simple calculation. I can of course just multiplay the sliderValue inside the TextView - that works well.

Text("\(sliderValue * 10)")

But is there a way to put this into another function to be more flexible, especially if the calculation get's more complex? It should still be live updated whenever the slider is dragged.

Here is the full code a bit beautified. Maybe you can explain to me how this works in SwiftUI?

struct ContentView: View {

    @State private var sliderValue: Double = 0

    var body: some View {
        VStack(alignment: .leading) {
            VStack(alignment: .leading) {
                Text("value".uppercased())
                    .font(.largeTitle)
                    .fontWeight(.bold)
                Text("\(sliderValue)")
                    .font(.system(size: 60, weight: .bold))
                Text("new value".uppercased())
                    .font(.largeTitle)
                    .fontWeight(.bold)
                Text("\(sliderValue * 10)") // I'd like to put this into a function somehow!?
                    .font(.system(size: 60, weight: .bold))
            }


            Slider(value: $sliderValue, in: 0...100, step: 1)
                .padding(8)
                .overlay(
                    Capsule()
                        .stroke(Color.purple, style: StrokeStyle(lineWidth: 5))
            )


        }//END: VSTACK
        .padding()
    }
}

Thanks for your help!

Upvotes: 3

Views: 506

Answers (2)

pawello2222
pawello2222

Reputation: 54651

I'd recommend a computed property just for calculations:

var calculatedValue: Double {
    sliderValue * 10
    // or some more complex calculations...
}

The calculatedValue will always be up to date with the sliderValue.

Then you can use Asperi's answer to move your TextView to another function or just leave it where it is.

Text("\(calculatedValue)")
    .font(.system(size: 60, weight: .bold))

Upvotes: 1

Asperi
Asperi

Reputation: 258541

Here is possible approach

struct ContentView: View {

    @State private var sliderValue: Double = 0

    var body: some View {
        VStack(alignment: .leading) {
            VStack(alignment: .leading) {
                Text("value".uppercased())
                    .font(.largeTitle)
                    .fontWeight(.bold)
                Text("\(sliderValue)")
                    .font(.system(size: 60, weight: .bold))
                Text("new value".uppercased())
                    .font(.largeTitle)
                    .fontWeight(.bold)

                self.calculatedView(for: sliderValue)
            }

            Slider(value: $sliderValue, in: 0...100, step: 1)
                .padding(8)
                .overlay(
                    Capsule()
                        .stroke(Color.purple, style: StrokeStyle(lineWidth: 5))
            )


        }//END: VSTACK
        .padding()
    }

    private func calculatedView(for value: Double) -> some View {
        Text("\(value * 10)")
            .font(.system(size: 60, weight: .bold))
    }
}

and here is another possible approach

struct ContentView: View {

    @State private var sliderValue: Double = 0

    var body: some View {
        VStack(alignment: .leading) {
            VStack(alignment: .leading) {
                Text("value".uppercased())
                    .font(.largeTitle)
                    .fontWeight(.bold)
                Text("\(sliderValue)")
                    .font(.system(size: 60, weight: .bold))
                Text("new value".uppercased())
                    .font(.largeTitle)
                    .fontWeight(.bold)

                CalculatedView(value: sliderValue)
            }

            Slider(value: $sliderValue, in: 0...100, step: 1)
                .padding(8)
                .overlay(
                    Capsule()
                        .stroke(Color.purple, style: StrokeStyle(lineWidth: 5))
            )


        }//END: VSTACK
        .padding()
    }
}

struct CalculatedView: View {
    let value: Double

    var body: some View {
        Text("\(value * 10)")
            .font(.system(size: 60, weight: .bold))
    }
}

Upvotes: 1

Related Questions