Initialize @StateObject with a parameter in SwiftUI
I would like to know if there is currently (at the time of asking, the first Xcode 12.0 Beta) a way to initialize a @StateObject
with a parameter coming from an initializer.
To be more specific, this snippet of code works fine:
struct MyView: View {
@StateObject var myObject = MyObject(id: 1)
}
But this does not:
struct MyView: View {
@StateObject var myObject: MyObject
init(id: Int) {
self.myObject = MyObject(id: id)
}
}
From what I understand the role of @StateObject
is to make the view the owner of the object.
The current workaround I use is to pass the already initialized MyObject instance like this:
struct MyView: View {
@ObservedObject var myObject: MyObject
init(myObject: MyObject) {
self.myObject = myObject
}
}
But now, as far as I understand, the view that created the object owns it, while this view does not.
Thanks.
Solution 1:
The answer given by @Asperi should be avoided Apple says so in their documentation for StateObject.
You don’t call this initializer directly. Instead, declare a property with the @StateObject attribute in a View, App, or Scene, and provide an initial value.
Apple tries to optimize a lot under the hood, don't fight the system.
Just create an ObservableObject
with a Published
value for the parameter you wanted to use in the first place. Then use the .onAppear()
to set it's value and SwiftUI will do the rest.
Code:
class SampleObject: ObservableObject {
@Published var id: Int = 0
}
struct MainView: View {
@StateObject private var sampleObject = SampleObject()
var body: some View {
Text("Identifier: \(sampleObject.id)")
.onAppear() {
sampleObject.id = 9000
}
}
}
Solution 2:
Here is a demo of solution. Tested with Xcode 12b.
class MyObject: ObservableObject {
@Published var id: Int
init(id: Int) {
self.id = id
}
}
struct MyView: View {
@StateObject private var object: MyObject
init(id: Int = 1) {
_object = StateObject(wrappedValue: MyObject(id: id))
}
var body: some View {
Text("Test: \(object.id)")
}
}