Resolver
Resolver copied to clipboard
Can't use existential 'any' with InjectedObject property wrapper
I can't use the existential 'any' keyword with @InjectedObject property wrapper, the fired error is:
Type 'any Test' cannot conform to 'ObservableObject'
the example is as follows:
protocol Test: ObservableObject {
}
class MyViewModel: Test {
}
struct MyView: View {
@InjectedObject var viewModel: any Test //<---- the error fires here
var body: some View {
Text("Hello")
}
}
You might take a look at the following.
https://medium.com/swlh/did-swiftui-just-kill-protocol-oriented-programming-c09c2787172
Making the VM a protocol is a bad idea, and suffers from a plethora of problems.
https://stackoverflow.com/questions/59503399/how-to-define-a-protocol-as-a-type-for-a-observedobject-property
I have read the article and the SO question, the article strongly recommends to inject a loader object into the view model and this loader can be safely a protocol not the view model itself, which I exactly did in my real project, but the view model itself, in a real world example, is not a simple load and set published properties, it may have lots of other functions that need to be tested, giving this difficulty of using the view model as a protocol I can only mock the view model using class inheritance which's not the best way for mocking. I can't use generics too to workaround this issue, as it forces me to specialize the view model class type once I define the view causing lots of other view issues in my complex project.
This is really an issue with Swift and associated types and there really isn't a lot I can do about it other than say, "Don't do that."
If the VM is as complex as you say, then IMHO that's even more reason to follow the advice I gave in the article so that you can test the code appropriately. A VM doesn't exist in a vacuum. If you change its dependencies and/or parameters then you should be able to mock any associated behavior.
Thank you for the advice anyway.