我们如何从 SwiftUI 中的其他结构中读取 @State 变量?

Posted

技术标签:

【中文标题】我们如何从 SwiftUI 中的其他结构中读取 @State 变量?【英文标题】:How we can read @State variable from other struct in SwiftUI? 【发布时间】:2020-10-28 15:24:16 【问题描述】:

我想知道是否有简单或正确的方法从不同的视图读取状态变量值,我知道 .onChange 或 Binding 或 ObservableObject(class) 的用法和...,但我想知道的是还有其他更好的方法吗?

例如,在这段代码中,我有一个名为 TextView 的视图,它有一个状态值,我在我的 ContentView 中调用这个视图,现在我在我的 ContentView 中放置一个文本,我想读取 TextView 的状态值。这项工作有空间方法吗?

struct ContentView: View 
    @State var readStringOfTextView: String = ""

    var body: some View 
        TextView()

        Text(readStringOfTextView)
            .foregroundColor(Color.blue)
    


struct TextView: View 
    @State var stringOfText: String = "Hello, world!"

    var body: some View 
        Text(stringOfText)
            .padding()
            .foregroundColor(Color.red)
    

【问题讨论】:

【参考方案1】:

State 的全部意义在于它在 View 的内部。如果您尝试在其他地方阅读它,那么您的设计中出现了问题。在这种情况下,您需要的工具是 @Binding。 ContentView 应该将 Binding 传递给 TextView。 ContentView 将看到 TextView 中的任何更改(在您的示例中,这没有意义,因为stringOfText 无法更改,但我假设您的其余代码会以某种方式更改它)。在您的示例中,这看起来像这样:

struct ContentView: View 
    @State var readStringOfTextView: String = ""
    var body: some View 
        TextView(stringOfText: $readStringOfTextView)
        Text(readStringOfTextView)
            .foregroundColor(Color.blue)
    


struct TextView: View 
    @Binding var stringOfText : String

    var body: some View 
        Text(stringOfText)
            .padding()
            .foregroundColor(Color.red)
            .onAppear 
                stringOfText = "Hello, world!"
            
    

可以使用首选项直接将数据向上传递到视图层次结构,但它要复杂得多,而且不是解决您所描述问题的正确工具。即便如此,它是这样的:

创建一个 PreferenceKey 来传递数据 使用.preference 在子视图中设置 PreferenceKey 使用.onPreferenceChange.overlayPreferenceValue.backgroundPreferenceValue读取父视图中的PreferenceKey。
struct TextPreference: PreferenceKey 
    static var defaultValue = "default"
    static func reduce(value: inout String, nextValue: () -> String) 
        value = nextValue()
    


struct ContentView: View 
    @State var readStringOfTextView: String = ""

    var body: some View 
        VStack 
            TextView()
                .onPreferenceChange(TextPreference.self)  value in
                    readStringOfTextView = value
                
            Text(readStringOfTextView)
                .foregroundColor(Color.blue)
        
    


struct TextView: View 
    @State var stringOfText : String = "Hello, world!"

    var body: some View 
        Text(stringOfText)
            .padding()
            .foregroundColor(Color.red)
            .preference(key: TextPreference.self, value: stringOfText)
    

【讨论】:

正如我所说,我已经知道 State 和 Binding 的用法,. . . TextView 是没有观察到的东西!你把绑定放在那里!请看我的代码。我想阅读 TextView 的状态,也许更接近和更合乎逻辑的方式是 ObservableObject 在 TextView 和 ContentView 之间共享,有人可以读或写,我正在寻找更好的方法 是的,如果您有状态希望多个视图都观察和共享,ObservableObject 将是正确的工具。您不得阅读其他视图状态。状态是明确的内部的。首选项也适用于此,但通常不是您所描述的那种东西的正确工具。如果它是“类似模型的”,那么您需要一个 Observable。 所以,这就是我问这个问题的原因,我不确定是否有比 ObservableObject 方法更好的方法!当我要使用 ObservableObject 时,我正在做颠倒的工程来解决这个问题,在这种情况下,我使用的不是 State 而是 StateObject,所以说 State 不能从外部访问,但 StateObject 是正确的! !我可以说最好和正确的答案是 StateObject 吗? StateObject 为 View 提供了一些原本是 ObservedObject 的东西的所有权。这很方便,因为这意味着在***视图中,您不需要传入对象。但您仍然不能尝试询问子视图的 StateObjects。 “状态”的东西总是私有的。视图永远不是更高级别视图(或系统的其他部分)状态的所有者。 WWDC20:developer.apple.com/videos/play/wwdc2020/10040

以上是关于我们如何从 SwiftUI 中的其他结构中读取 @State 变量?的主要内容,如果未能解决你的问题,请参考以下文章

从 SwiftUI 列表中的每个元素获取用户输入

将数据从委托 Swift 类传递到 SwiftUI 结构中的 EnvironmentObject

从选择器 SwiftUI 中读取选择

如何从 SwiftUI 中的结构返回值?

编写 SwiftUI 模型以从带有数组的 JSON 文件中读取

我们如何在 SwiftUI 中读取和写入相同的 ObservableObject?