hmlongco / Factory

A new approach to Container-Based Dependency Injection for Swift and SwiftUI.
MIT License
1.93k stars 116 forks source link

Cannot form key path to main actor-isolated property; this is an error in Swift 6 #207

Closed ulian-onua closed 5 months ago

ulian-onua commented 5 months ago

I got a warning like this when injecting a service marked with @MainActor.

image

This warning is also displayed even if a class where a dependency is injected is also @MainActor.

This warning disappears if the @MainActormodifier is removed from the injected service, but it is not a desirable solution.

Any ideas or suggestions on how to solve that?

Thank you.

hmlongco commented 5 months ago

See pinned issue: https://github.com/hmlongco/Factory/issues/135

ulian-onua commented 5 months ago

@hmlongco thank you for a quick answer. I got your idea. IMHO, it looks to me like a Swift 6 or Xcode compiler issue if a class is @MainActorand I inject @MainActor dependency, it shouldn't comply as all properties of this class should be isolated to @MainActor.

ulian-onua commented 5 months ago

@hmlongco I believe it is still a Swift Compiler issue. What if I want to register a UIKit view and inject it then? A UIKit view is @MainActorbecause it is set in Apple code, and we can't do anything here.

If Apple doesn't solve that, please think about how it can be solved on the Factory level.

This issue limits the usage of Factory for many cases.

ulian-onua commented 5 months ago

@hmlongco I found a workaround for this case.

We can use a computed or lazy var property and resolve manually inside it (that can be used until Apple solves that bug).

@MainActor
var rendererService: RendererService? { Container.shared.rendererService.resolve() }

Is this approach significantly slower if we use it instead of the default @Injected attribute? Can it be connected with some memory leaks or additional downsides? Thank you.

hmlongco commented 5 months ago

@Injected just uses a keypath to effectively do the same thing, but keep in mind your code will cause a new version of the service to be instantiated every time it's referenced. Probably need to make sure the Factory for RendererService is cached (.shared), and that's especially true if this is occurring in a SwiftUI View that's constantly being evaluated for updates.

ulian-onua commented 5 months ago

@hmlongco thank you for your answer!