繁体   English   中英

如何从 SwiftUI 中的 en EnvironmentObject 加载 state?

[英]How can I load state from en EnvironmentObject in SwiftUI?

所以我正在处理一个视图,我想从一个类似于数据库的 EnvironmentObject 加载 state。

我想实现这样的目标:

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 传递给子视图,然后在显示视图之前从这个环境 object loadState state 和 loadState function。

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

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

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

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

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

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

// 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)
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM