因此,我正在处理一个视图,在该视图中,我希望从类似数据库的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
从环境中读取。
尝试使用不同的方法,例如以下代码,其中children
和name
是MyDB
的已发布变量函数只是将数据加载到这些函数中。
// 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)
}
}