hmlongco / Resolver

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

WeakLazyInjected not working on class protocols #81

Closed corban123 closed 3 years ago

corban123 commented 3 years ago

I've got

@WeakLazyInjected(container: .api) var userAuthAPI: UserAuthenticationAPIType?

and

public protocol UserAuthenticationAPIType: class {

however I still receive

Generic struct 'WeakLazyInjected' requires that 'UserAuthenticationAPIType' be a class type

What's going on? Class-only protocols generally work with Weak.

corban123 commented 3 years ago

As a note, LazyInjected works fine on these objects

hmlongco commented 3 years ago

First, I'd note that class is deprecated in favor of AnyObject. (https://sarunw.com/posts/class-only-protocols-class-or-anyobject/)

Second, there seems to be some weirdness in regard to protocols. Try adding this to your project and see what happens if you use TestWeakLazyInjected instead.

@propertyWrapper
public struct TestWeakLazyInjected<Service> {
    private var initialize: Bool = true
    private weak var service: AnyObject?
    public var container: Resolver?
    public var name: String?
    public var args: Any?
    public init() {}
    public init(name: String? = nil, container: Resolver? = nil) {
        self.name = name
        self.container = container
    }
    public var isEmpty: Bool {
        return service == nil
    }
    public var wrappedValue: Service? {
        mutating get {
            if initialize {
                self.initialize = false
                let service = container?.resolve(Service.self, name: name, args: args) ?? Resolver.resolve(Service.self, name: name, args: args)
                self.service = service as AnyObject
                return service
            }
            return service as? Service
        }
        mutating set { service = newValue as AnyObject }
    }
    public var projectedValue: TestWeakLazyInjected <Service> {
        get { return self }
        mutating set { self = newValue }
    }
}
corban123 commented 3 years ago

I'm unable to add it as I receive the error (744, 32) 'WeakLazyInjected' requires that 'Service' be a class type

corban123 commented 3 years ago

I also attempted to swap the protocol type over to AnyObject, no dice

hmlongco commented 3 years ago

I updated the above code as ProjectedValue needed to be same type.

corban123 commented 3 years ago

Perfect. Tested now, it seems that yes, it compiles when using the TestWeakLazyInjected on my protocol.

corban123 commented 3 years ago

Will this get added to a 1.2.2 release?

3Qax commented 3 years ago

I ran into the same issue. I can confirm that @hmlongco's TestWeakLazyInjected implementation works.

hmlongco commented 3 years ago

Will be in 1.3. See current develop branch.