【问题标题】:How to update variable proper in different struct Swift如何在不同的结构 Swift 中正确更新变量
【发布时间】:2020-05-11 21:27:20
【问题描述】:

在下面的代码中,变量“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())

【问题讨论】:

  • 你在哪里改变 yourVariable 的值?

标签: swift swiftui swift-playground


【解决方案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 已经提到的,我不建议对结构使用这种方法。

【讨论】:

  • 我应该把@Binding 放在哪里?我可以使用多少个变量?
  • @EliasFizesan 而不是@State public var slidetwo = MyVariables.yourVariable + 60000。但不要忘记用560000.0 而不是500000.0 来初始化static var yourVariable。 @Binding 注释允许您“同步”您对slideTwo 的更改,这意味着每当您更改此值时,您的MyVariables.yourVariable 也将由于我在第二个代码sn-p 中提供的getter/setter 而更新我的回答。
  • 我不明白你的问题“我可以使用多少个变量?”。您可以根据需要设置任意数量的变量。
【解决方案2】:

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

当您打开第二个视图时,您将结构的值放入变量string 女巫将导致始终具有由yourVariable 定义的值,因此移动滑块根本不会影响第二个视图.

为了正确执行此操作,您可以使用Binding,以防您希望在第二个视图中更改变量并在ContentView 或简单的未初始化@State var 中反映这些更改

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

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

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

更新 1:

根据您的评论,我的理解是您希望 SecondView 有多个变量,如果是这种情况,您最好使用 ObservableObjectEnvironmentObject

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

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
    }
}

现在我们将在第一个视图上更新数据的模型发送到第二个视图,任何更改都将反映在两个视图中,最后一件事,在第二个视图上捕获这个 EnvironmentObject

struct SecondView: View {
    // var string = MyVariables.yourVariable <- no longer needed
    @EnvironmentObject var model: MyVariables
    // ....
}

在这种情况下,model.yourVariable 仍然没有改变,因为我们正在更新 model.slidertwo 变量。 对模型所做的更改将反映在两个视图中。

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

【讨论】:

  • 检查更新的响应,基本上你使用一个继承自ObservableObject的类,所有解释
  • 请注意,我没有在回复中添加,有时如果您只需要两个变量,您可以使用两个@Bindings,您可以使用任意数量但您会得到一个凌乱的代码,这样你可以添加任意数量的变量,并且仍然保持代码干净;)
  • 除了pastebin.com/gL4vh8rs 之外,我无法为您提供更多帮助,而且我不喜欢这样做,但因为我的回复包含完全相同的回复但已解释。我希望至少你试图理解它。我提供的粘贴是使用 ObservedObject 实现的问题的代码,并注释掉了不再需要的代码。还在第二个视图中添加了两个按钮,以查看 ObservedObject 的运行情况
  • 你检查过我提供的粘贴吗?那个粘贴在操场上完全可以工作
  • 在没有看到代码的情况下无法为您提供更多帮助。可能有些东西你忘了改,我不知道,可能是滑块链接到了错误的变量
猜你喜欢
  • 1970-01-01
  • 2022-08-23
  • 2015-01-07
  • 2022-01-01
  • 2017-12-16
  • 1970-01-01
  • 2021-11-05
  • 1970-01-01
  • 2014-03-14
相关资源
最近更新 更多