首页 > 解决方案 > @ObservableObject 的 Swift 链

问题描述

在我的 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 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)。

标签: swiftclassobservable

解决方案


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

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

  2. @Published只有在使用值类型时才能开箱即用。在 Swift 中,这意味着使用structs 而不是classes。

关于第二点,除非有真正令人信服的理由不这样做,否则您的模型应该是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()手动调用以告诉您的 SwiftUIView@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 嵌套的 ObservableObject”,这将为您提供有关此主题的大量现有对话,包括:

如何告诉 SwiftUI 视图绑定到嵌套的 ObservableObjects


推荐阅读