创建一个@State var 区域,即基于两个@State var 宽度,一个@State var 高度

use*_*406 3 swift swiftui xcode11

你如何组合多个状态变量来形成另一个?

我想通过一些用户交互来更改高度或宽度的值,并相应地更新视图中的所有内容。所以高度或宽度会改变,面积也会改变。

我想它看起来像这样

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


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

Run Code Online (Sandbox Code Playgroud)

当前的解决方案只是调用一个函数

func area() -> CGFloat {
  width * height
}
Run Code Online (Sandbox Code Playgroud)

RPa*_*l99 7

不要做area @State; 只需将其设为计算变量即可:

@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")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我添加了一些代码来说明如果widthheight更改,area也会更改,因为widthheight更改导致视图被重绘,因为它们是@State. 由于area是计算的,所以当视图被重绘时,area被确定为更新widthheight值的乘积。不过,将其作为您在当前解决方案中所说的功能也应该有效。

如果你想area成为@State这样就可以将它传递给为其他视图Binding,这样做:

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)")
    }
}
Run Code Online (Sandbox Code Playgroud)

我创建BindingView了一个示例,说明如何以不同方式使用绑定。对于@State变量,您可以Binding通过添加$前缀有效地将它们转换为 a ,但由于 area 是明确的Binding,因此您不需要$. 同样要访问 中的值Binding,您只需执行变量.wrappedValue.