问题
I'm not sure if this is an antipattern in this brave new SwiftUI world we live in, but essentially I have an @EnvironmentObject with some basic user information saved in it that my views can call.
I also have an @ObservedObject that owns some data required for this view.
When the view appears, I want to use that @EnvironmentObject to initialize the @ObservedObject:
struct MyCoolView: View {
@EnvironmentObject userData: UserData
@ObservedObject var viewObject: ViewObject = ViewObject(id: self.userData.UID)
var body: some View {
Text("\(self.viewObject.myCoolProperty)")
}
}
Unfortunately I can't call self on the environment variable until after initialization:
"Cannot use instance member 'userData' within property initializer; property initializers run before 'self' is available."
I can see a few possible routes forward, but they all feel like hacks. How should I approach this?
回答1:
Here is the approach (the simplest IMO):
struct MyCoolView: View {
@EnvironmentObject var userData: UserData
var body: some View {
MyCoolInternalView(ViewObject(id: self.userData.UID))
}
}
struct MyCoolInternalView: View {
@EnvironmentObject var userData: UserData
@ObservedObject var viewObject: ViewObject
init(_ viewObject: ViewObject) {
self.viewObject = viewObject
}
var body: some View {
Text("\(self.viewObject.myCoolProperty)")
}
}
回答2:
instead of creating a subview you can add a dummy initializer to your "ViewObject" so that you can call it before calling the real initializer
struct MyCoolView: View {
@EnvironmentObject userData: UserData
@ObservedObject var viewObject: ViewObject
init() {
viewObject = ViewObject()
defer {
viewObject = ViewObject(id: self.userData.UID)
}
}
var body: some View {
Text("\(self.viewObject.myCoolProperty)")
}
}
for the record i haven't tested it
回答3:
Here is an easy way to to it:
struct MyCoolView: View {
@EnvironmentObject var userData: UserData
var body: some View {
Observe(obj: ViewObject(id: userData.UID)) { viewObject in
Text("\(viewObject.myCoolProperty)")
}
}
}
With this helper that makes it work:
struct Observe<T: ObservableObject, V: View>: View {
@ObservedObject var obj: T
let content: (T) -> V
var body: some View { content(obj) }
}
来源:https://stackoverflow.com/questions/59367218/swiftui-how-do-i-initialize-an-observedobject-using-an-environmentobject-as-a