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

时间:2019-10-15 01:23:42

标签: swift swiftui xcode11

您如何组合多个状态变量以形成另一个状态?

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

我想它看起来像这样

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


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

当前解决方案只是调用func

func area() -> CGFloat {
  width * height
}

1 个答案:

答案 0 :(得分:3)

请勿创建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")
        }
    }
}

我添加了一些代码来说明如果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)")
    }
}

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