I am trying to use Swift 5.1 property wrappers but every time I think I have a cool use case for it, I eventually hit the problem where I can't use them inside of my View Model's initializer.
Take this extremely simple example.
class NoProblem {
var foo = "ABC"
let upperCased: String
init(dependencies: AppDependencies) {
self.upperCased = foo.uppercased()
}
}
@propertyWrapper
struct Box<Value> {
private var box: Value
init(wrappedValue: Value) {
box = wrappedValue
}
var wrappedValue: Value {
get { box }
set { box = newValue }
}
}
class OhNoes {
@Box var foo = "ABC"
let upperCased: String
init(dependencies: AppDependencies) {
self.upperCased = foo.uppercased()
}
}
In NoProblem
, everything works as expected. However in OhNoes
I get this error: 'self' used in property access 'foo' before all stored properties are initialized
.
Of course this is an extremely simplified example, but I get the same problem when doing an @Property
wrapper for observable properties, or an @Injected
wrapper like in this article, etc.
And no, sadly making it a lay property won't work either: Property 'foo' with a wrapper cannot also be lazy
.
This is also a pretty big problem in SwiftUI, see this example:
class AppStore: ObservableObject {
let foo = "foo"
}
struct ContentView: View {
@EnvironmentObject private var store: AppStore
private let foo: String
init() {
foo = store.foo // error: 'self' used before all stored properties are initialized
}
var body: some View {
Text("Hello world")
}
}