Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

create a @State var area, that is based on two @State var width, an @State var height

How do you combine multiple state variables to form another?

I want to change the value of height OR width by some user interaction, and have everything in the view update accordingly. So the height OR width would change, and the area would change.

I imagine it would look something like this

@State var width: CGFloat = 50.0
@State var height: CGFloat = 100.0


@State var area: CGFloat // somehow equal to width*height

current solution is just calling a func

func area() -> CGFloat {
  width * height
}
like image 737
user1990406 Avatar asked Oct 17 '25 15:10

user1990406


1 Answers

Don't make area @State; just make it a computed variable:

@State var height: CGFloat = 50.0
@State var width: CGFloat = 100.0
var area: CGFloat {
    width * height
}
var body: some View {
    VStack {
        Text("Width: \(width)")
        Text("Height: \(height)")
        Text("Area \(area)")
        Button(action: {
            self.height *= 2
        }) {
            Text("Double height")
        }
        Button(action: {
            self.width += 10
        }) {
            Text("Add 10 to width")
        }
    }
}

I added some code to illustrate that if width or height changes, area will change too, because width or height changing cause the view to be redrawn since they are @State. Since area is computed, when the view is redrawn, area is determined to be the product of the updated width and height values. Doing it as a function like you said in your current solution should also work, though.

If you want area to be @State so that you can pass it to other views as a Binding, do this:

struct ContentView: View {
@State var height: CGFloat = 50.0
@State var width: CGFloat = 100.0
var area: Binding<CGFloat> {
    Binding(get: {
        self.height * self.width
    }) { (newVal) in

    }
}
var body: some View {
    VStack {
        Text("Width: \(width)")
        Text("Height: \(height)")
        Text("Area \(area.wrappedValue)")
        BindingView(num: area)
        BindingView(num: $height)
        Button(action: {
            self.height *= 2
        }) {
            Text("Double height")
        }
        Button(action: {
            self.width += 10
        }) {
            Text("Add 10 to width")
        }
    }
}

struct BindingView: View {
    @Binding var num: CGFloat
    var body: some View {
        Text("Binding number: \(num)")
    }
}

I created BindingView as an example of how to use bindings in different ways. For @State variables, you effectively turn them into a Binding by adding the $ prefix, but since area is explicitly Binding, you do not need the $. Also to access the value inside the Binding, you just do the variable .wrappedValue.

like image 70
RPatel99 Avatar answered Oct 20 '25 08:10

RPatel99



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!