Swift @ObservableObject 链

Swift chains of @ObservableObject

在我的Swift项目中,数据和触发数据变化的前端按钮被几层对象隔开。如何使前端视图反映出删除了多个层的更改?我想这在 Swift 开发中是相当普遍的情况。

这是一个工作示例,视图和数据之间没有分隔层。

import Foundation
import SwiftUI
import OrderedCollections

class Test: ObservableObject {
    @Published var array: [String] = []
    var num: Int = 0
    
    func add() {
        array.append(String(num))
        num += 1
    }
}


struct testView: View {
    @ObservedObject var test = Test()
    var body: some View {
        VStack {
            Button(action: { test.add() }) {
                Text("Add Item to Array")
            }
            Text("")
            Text("Items")
            Text(Array(test.array).description)
        }
    }
}

@main
struct app: App {
    var body: some Scene {
        WindowGroup {
            testView()
        }
    }
}

这是一个“中间”的例子 class 不起作用。

class Test: ObservableObject {
    @Published var array: [String] = []
    var num: Int = 0
    
    func add() {
        array.append(String(num))
        num += 1
    }
}

class Middle: ObservableObject {
    @ObservedObject var test: Test = Test()
}


struct testView: View {
    @ObservedObject var m = Middle()
    var body: some View {
        VStack {
            Button(action: { m.test.add() }) {
                Text("Add Item to Array")
            }
            Text("")
            Text("Items")
            Text(Array(m.test.array).description)
        }
    }
}

@main
struct app: App {
    var body: some Scene {
        WindowGroup {
            testView()
        }
    }
}

注意:使用其他代码,我似乎已经能够让我的视图更新远离前端的变化数据。我确信这是可能的——我正在寻找的是使这项工作有效的系统方法(我目前的方法只是将@ObservableObject、@Published 和@ObservedObject 添加到数据接触的所有内容中,直到它有效——或无效” t).

可能有一些元素很好理解。最重要的是:

  1. @ObservedObject属性包装器用于View——如果在内部使用它不会做任何事情另一个ObservableObject

  2. @Published 仅在使用值类型时开箱即用。在 Swift 中,这意味着使用 struct 而不是 class

关于第二点,除非有真正令人信服的理由,否则您的模型应该是 structs。这意味着您可以只使用 @Published 属性 来存储它们,一切都会起作用:

struct Test {
    var array: [String] = []
    var num: Int = 0
}

class Middle: ObservableObject {
  @Published var test: Test = Test()

  func append() {
    test.array.append(String(test.num))
    test.num += 1
  }
}

如果由于某种原因你必须使用嵌套对象,你将不得不手动调用objectWillChange.send()来告诉你的SwiftUI View @Published 属性 有新数据:

class Test : ObservableObject {
    var array: [String] = []
    var num: Int = 0
    
    func append() {
      array.append(String(num))
      num += 1
    }
}

class Middle: ObservableObject {
  @Published var test: Test = Test()

    func append() {
        test.append()
        self.objectWillChange.send()
    }
}

您还可以搜索“SwiftUI nested ObservableObject”,这将为您提供大量关于此主题的现有对话,包括: