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

Posted

技术标签:

【中文标题】我们如何在 SwiftUI 中读取和写入相同的 ObservableObject?【英文标题】:How we can read and write to same ObservableObject in SwiftUI? 【发布时间】:2020-10-28 18:00:30 【问题描述】:

我正在创建一个ObservableObject 类,然后我将它用于在所有应用程序中读取和写入值。当我在 StateObject 和 ObservedObject 中使用 ObservableObject 时,它们不是相同的数据,但它们在内存中创建了不同的变量,我们如何使 StateObjectObservedObject 处理相同的数据?

例如,我的 ObservableObject 类有一个名为 stringOfText 的变量,默认为 No Data! 然后我创建一个 StateObject 变量并开始读取默认值 stringOfText,然后我更改了 stringOfText 的默认值并且它确实不在我的ObservedObject 中显示更新!我做错了什么?

class TextModel: ObservableObject 
    @Published var stringOfText: String = "No Data!"


struct ContentView: View 
    @ObservedObject var readStringOfTextView = TextModel()

    var body: some View 
        TextView()

        Text(readStringOfTextView.stringOfText)
            .foregroundColor(Color.black)
    


struct TextView: View 
    @StateObject var textModel = TextModel()

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

        Button(action: 
            textModel.stringOfText = "Hello, world!"

        ) 
            Text("update string of Text")
                .padding()
        
    

【问题讨论】:

【参考方案1】:

我们如何让 StateObject 和 ObservedObject 处理相同的数据?

您可以通过共享实例来实现,例如:

class TextModel: ObservableObject 
    static let shared = TextModel()     // << here !!

    @Published var stringOfText: String = "No Data!"


struct ContentView: View 
    @ObservedObject var readStringOfTextView = TextModel.shared  // << here !!

// ... other code


struct TextView: View 
    @StateObject var textModel = TextModel.shared // << here !!

// ... other code

【讨论】:

谢谢,我刚刚将 TextView 中的 @StateObject 更改为 @ObservedObject 并且它起作用了。我也确实在 ContentView 中将@ObservedObject 更改为@StateObject,并且也有效,看来无论它们是什么都有效!我们可以将它们都更改为@StateObject,它会起作用,或者两者都更改为@ObservedObject,它也会起作用!所以让我问你,@ObservedObject 或@StateObject 有什么意义,因为它们对我来说是相同的结果。如果您认为这是不同的主题,请告诉我 @StateObject 必须像 @State 一样使用,@ObservedObject 必须像 @Binding 一样使用,以实现最佳内存管理。【参考方案2】:

您需要将TextModel 传递给子视图(在两个视图中使用相同的实例):

struct ContentView: View 
    @StateObject var readStringOfTextView = TextModel()

    var body: some View 
        TextView(textModel: readStringOfTextView) // pass here

        Text(readStringOfTextView.stringOfText)
            .foregroundColor(Color.black)
    


struct TextView: View 
    @ObservedObject var textModel: TextModel // declare only

    ...

【讨论】:

谢谢,我知道这种编码方式,TextView 是“真相的来源”,不应该观察任何东西!但是 ContentView 里面的 Text 应该小心改变 TextView 的值,它必须观察!我们怎么能做到这一点?你使用了这个不是我想要的代码“TextView(textModel:readStringOfTextView)”,它应该是TextView() @Omid 我认为您误解了上一个问题的答案。 应该是 TextView() - 我不同意。此外,您的 TextView 也不是事实来源。它只提供了一种操作数据的方法。试着专注于你想要实现的目标,而不是你需要使用什么工具。 可能是我理解错了,所以我要问和学习,我只想在同一个TextModel上读写,这个限制是TextView是源 @Omid 但不应该这样。你有什么特别的理由想要这样吗? 我刚刚学习 SwiftUI,我收到了这个问题,我知道这可能很愚蠢或很有趣,但我想知道,让我这样问我的问题:我们有 TextModel,好吗?默认值为“无数据!”,好吗?我们如何更新 TextModel 中 stringOfText 的默认值以供以后使用?

以上是关于我们如何在 SwiftUI 中读取和写入相同的 ObservableObject?的主要内容,如果未能解决你的问题,请参考以下文章

在磁盘上读取/写入文件时如何限制硬盘 I/O?

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

SDRAM 方向性 - 在“官方”带宽数据中读取和写入计数是不是相同?

如何在从 NodeJS 中的多个输入流中读取时写入单个文件

如何在不修改脚本的情况下计算 PHP 脚本的文件读取和写入?

Java I/O---RandomAccessFile类(随机访问文件的读取和写入)