【问题标题】:create a @State var area, that is based on two @State var width, an @State var height创建一个@State var 区域,即基于两个@State var 宽度,一个@State var 高度
【发布时间】:2019-10-15 01:23:42
【问题描述】:

如何将多个状态变量组合成另一个?

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

我想它看起来像这样

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


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

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

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

【问题讨论】:

    标签: swift swiftui xcode11


    【解决方案1】:

    不要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

    【讨论】:

    • 哦。所以计算变量area 会根据状态变量动态变化??也是的,这个绑定示例非常有用,因为在这种情况下我需要将它传递给孩子
    • 是的,计算变量的值只有在被访问时才确定(它们基本上只有一个getter),而且由于width和height是State变量,所以每当它们发生变化时,都会重绘视图,这会导致使用 area 变量“获取”其计算值,该值使用新的宽度和高度值。我同意,了解如何在没有状态、绑定等的情况下使用绑定非常有用。
    • 对,这就是为什么你可以用 get 和 set 来做所有有趣的计算变量的事情......好的。是的,到目前为止我只完成了状态变量的被动模式,并作为绑定传递给子视图
    • 没问题!为了纠正我之前所说的,计算属性可以有一个 setter,但只有 getter 是必需的;设置器是可选的。
    猜你喜欢
    • 2022-01-15
    • 2015-12-17
    • 1970-01-01
    • 2021-11-24
    • 2019-11-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多