如何在SwiftUI中从en-EnvironmentObject加载状态



因此,我正在处理一个视图,在该视图中,我希望从类似数据库的EnvironmentObject加载状态。

我想实现这样的目标:

class MyDB: ObservableObject {
func getName(_ id: RecordID) -> String { ... }
func getChildren(_ id: RecordID) -> [RecordID] { ... }
var didUpdate: PassthroughSubject...
}
struct TreeView: View {
let id: RecordID
@EnvironmentObject var db: DB
@State var name: String
@State var children: [RecordID]
func loadState() {
self.name = db.getName(id)
self.children = db. getChildren(id)
}
var body: some View {
Text(self.name)
List(self.children) { child in
TreeView(id: child)
}
.onReceive(self.db.didUpdate) { _ in
self.loadState()
}
}
}

因此,基本上我只想将树视图中节点的id传递给子视图,然后在显示视图之前用loadState函数从该环境对象加载状态。

有什么办法做到这一点吗?例如,我是否可以实现某种生命周期函数,它将在绑定环境后调用?

或者,例如,我可以在自定义init中实现loadState吗?

处理这个问题的惯用方法是什么?

如果您想查看,我在这里提供了一个解释。

您需要在父视图上使用.environmentObject(myDBInstance)传递MyDB实例,这样所有子视图都可以通过@EnvironmentObject从环境中读取。

尝试使用不同的方法,例如以下代码,其中childrennameMyDB的已发布变量函数只是将数据加载到这些函数中。

// for testing
struct RecordID: Identifiable {
let id = UUID().uuidString
var thing: String = ""
}
class MyDB: ObservableObject {
@Published var didUpdate: Bool = false
@Published var children: [RecordID] = []
@Published var name: String = ""

func getName(_ id: RecordID) {
// ...
name = "xxx"  // whatever
}

func getChildren(_ id: RecordID) {
// ...
children = [RecordID(), RecordID()] // whatever
}
}
struct TreeView: View {
@EnvironmentObject var db: MyDB
@State var id: RecordID

var body: some View {
Text(db.name)
List(db.children) { child in
//  TreeView(id: child)  // <-- here recursive call, use OutlineGroup instead
Text("(child.id)")
}
.onReceive(db.$didUpdate) { _ in
loadState()
}
}
func loadState() {
db.getName(id)
db.getChildren(id)
}

}
struct ContentView: View {
@StateObject var myDB = MyDB()
let recId = RecordID()

var body: some View {
TreeView(id: recId).environmentObject(myDB)
}
}

最新更新