hmlongco / Resolver

Swift Ultralight Dependency Injection / Service Locator framework
MIT License
2.14k stars 187 forks source link

Can't use existential 'any' with InjectedObject property wrapper #170

Open mobileuidev opened 1 year ago

mobileuidev commented 1 year ago

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")
    }
}
hmlongco commented 1 year ago

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

mobileuidev commented 1 year ago

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.

hmlongco commented 1 year ago

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.

mobileuidev commented 1 year ago

Thank you for the advice anyway.