如何在不同的结构Swift中正确更新变量

时间:2020-05-11 21:27:20

标签: swift swiftui swift-playground

在下面的代码中,变量“ yourVariable”在结构中定义。然后,我使用滑块更改“ yourVariable”,但是当我尝试在SecondView中使用该变量时,它使用的是原始变量,而不是更新的变量。有人告诉我我需要更新属性,我应该这样做吗?如果可以,请解释原因。

import SwiftUI
import PlaygroundSupport

struct MyVariables {
    static var yourVariable = 500000.0
}



struct SecondView : View {
    @Environment(\.presentationMode) var presentationMode
    var string = MyVariables.yourVariable
    var body: some View {
        VStack {Button("\(string)") {
            self.presentationMode.wrappedValue.dismiss()
            } 
        }
    }
}


struct ContentView : View {
    @State private var showingSheet = false

    @State public var step = 0
    @State public var text = ""
    @State public var slide = 20.0
    @State public var slidetwo = MyVariables.yourVariable + 60000
    var r0 : Double {
        rvalues[(wearingMaskToggle ? 1:0) + (washingHandsToggle ? 2:0) + (quarantineToggle ? 8:0) + (coverMouthToggle ? 4:0)]
    }
    @State private var rvalues = [6.5, 6.1, 5.3, 4.8, 4.2, 3.5, 3.1, 2.9, 1.75, 1.5, 1.2, 1.0, 0.92, 0.82, 0.75, 0.7]

    var body: some View {
        ZStack {
            Color.gray
                .edgesIgnoringSafeArea(.all)
                VStack {
                    HStack {
                        Button(action: {
                            if self.slidetwo > 10000{
                                self.slidetwo -= 1000 //When rand = 10050, it still works
                            }
                        }, label: {
                            Image(systemName: "minus")
                        })
                        Slider(value: $slidetwo, in: 10000...1000000, step: 1000)
                            .padding(20)
                            .accentColor(Color.green)
                        Button(action: {
                            if self.slidetwo < 1000000{
                                self.slidetwo += 1000
                            }
                        }, label: {
                            Image(systemName: "plus")
                        })
                    }.foregroundColor(Color.green) .padding(.horizontal, 100)
                }
                Text("Initial Population: \(Int(slidetwo))")

                Button("Show Sheet") {
                    self.showingSheet.toggle()
                }
                .sheet(isPresented: $showingSheet) {
                    SecondView()
                }
            }
        }
}
PlaygroundPage.current.setLiveView(ContentView())

2 个答案:

答案 0 :(得分:1)

恐怕为时已晚,但是您也可以在代码中进行调整,就是将slideTwo变量更改为。

@Binding public var slidetwo: Double

您必须直接在结构中添加+60000,然后按如下所示初始化视图:

PlaygroundPage.current.setLiveView(ContentView(slidetwo: .init(get: { () -> Double in
    return MyVariables.yourVariable
}, set: { (newValue) in
    MyVariables.yourVariable = newValue
})))

这将导致将对slideTwo的所有更改也应用到yourVariable。但是,正如Pedro已经提到的那样,我不建议将这种方法与struct一起使用。

答案 1 :(得分:0)

首先,滑块将更新变量slidetwo,其初始值为560000

打开第二个视图时,将结构的值存储到变量string中,将始终具有yourVariable定义的值,因此移动滑块不会影响所有第二个视图。

为了正确地执行此操作,如果希望在第二个视图内更改变量并在Binding或简单的未初始化{中反映这些更改,可以使用ContentView {1}}

使用第二个选项将导致将@State var SecondView中的var string = MyVariables.yourVariable替换为

然后在工作表内的@State var string: String中调用ContentView而不是SecondView(string: String(slidetwo))

我不知道为什么在这里需要一个结构。它所做的只是保留一个默认值,仅此而已,并且您不会在任何地方更新该变量。您无法直接更新它,因为它无法绑定。

更新1:

根据您的评论,我了解到您希望将多个变量传递给SecondView,如果是这种情况,最好将SecondView()ObservableObject结合使用

这很容易做到。首先创建一个包含所有变量的类。该类继承自EnvironmentObject

ObservableObject

现在在第一个视图上,您​​想要初始化该类并在需要的地方使用它。此时,幻灯片2不会更新class MyVariables: ObservableObject { @Published var sliderTwo: Double = 0.0 @Published var yourVariable = 500000.0 // <- I don't know the purpose of this init() { sliderTwo = yourVariable + 60000 // <- This is the original value, in the original code } } 变量,而是模型中的变量,我们将需要像这样将@State传递给第二个视图。

ObservedObject

现在,我们将模型和在第一个视图上更新的数据发送到第二个视图,所有更改都将反映在两个视图中,这只是最后一件事,请在第二个视图上捕获此struct ContentView: View { @ObservedObject var model: MyVariables = MyVariables() //@State public var slidetwo = MyVariables.yourVariable + 60000 <- no longer needed // ... change every other reference of slidertwo to model.slidertwo // except the following one witch instead of $slidertwo it will be $model.slidertwo Slider(value: $model.slidertwo, in: 10000...1000000, step: 1000) // ... .sheet(isPresented: $showingSheet) { SecondView().environmentObject(self.model) // send the model as an environment object } } < / p>

EnvironmentObject

在这种情况下,struct SecondView: View { // var string = MyVariables.yourVariable <- no longer needed @EnvironmentObject var model: MyVariables // .... } 仍然没有改变,因为我们正在更新model.yourVariable变量。 对模型所做的更改将反映在两个视图中。

根据我的经验,这是在SwiftUI中做事的正确方法