Angad
Angad

Reputation: 2823

Swift can't find method guaranteed by protocol

I'm trying to come up with a way to reduce boilerplate-code for dependency injection with Cleanse into ViewControllers. However, absolutely stuck here inside my type-erasure class for the Cleanse.Component boilerplate. What am I doing wrong?

(including both Code, as well as XCode snapshot, for your reading ease)

import Foundation
import Cleanse

protocol CleanseInjectable {
    func inject(args: Any...) -> Void
    func prepare() -> Void
}

extension CleanseInjectable {
    func inject(args: Any...) -> Void {

    }
}

class AnyCleansePropertyInjectionComponent<TargetType: AnyObject, CleanseInjectable>: Cleanse.Component {
    typealias Root = PropertyInjector<TargetType>

    func configure<B : Binder>(binder binder: B) {
        binder
            .bindPropertyInjectionOf(TargetType.self)
            .to(injector: (TargetType.self as! CleanseInjectable.Type).inject)
    }
}

The error I'm getting is as bizarre as any Swift protocol-error that is only obvious in hindsight: Type 'CleanseInjectable' has no member 'inject'?!

XCode Snapshot

Upvotes: 0

Views: 138

Answers (1)

Angad
Angad

Reputation: 2823

This revision seems to fix the error! It seems Swift was unable to comprehend that TargetType: AnyObject, CleanseInjectable is constraints-wise equivalent to protocol CleanseInjectable: class.

import Cleanse

protocol CleanseInjectable: class {
    func inject(args: Any...) -> Void
    func prepare() -> Void
}

extension CleanseInjectable {
    func inject(args: Any...) -> Void {

    }
}

class AnyCleansePropertyInjectionComponent<TargetType: CleanseInjectable>: Cleanse.Component {
    typealias Root = PropertyInjector<TargetType>

    func configure<B : Binder>(binder binder: B) {
        binder
            .bindPropertyInjectionOf(TargetType.self)
            .to(injector: TargetType.inject)
    }
}

Edit: My completed Cleanse boiler-plate remover (untested in runtime, will update at earliest), for fun and inspiration!

import Cleanse

protocol CleanseInjectable: class {
    var cleanseComponent: AnyCleansePropertyInjectionComponent<Self>? { get }
    func inject(args: Any...) -> Void
    func prepare() -> Void
}

extension CleanseInjectable {
    func inject(args: Any...) -> Void {
        // Override me to do something useful, brah!
    }

    func prepare() -> Void {
        if (cleanseComponent != nil) {
            (try! cleanseComponent!.build()).injectProperties(into: self)
        }
    }
}

class AnyCleansePropertyInjectionComponent<TargetType: CleanseInjectable>: Cleanse.Component {
    typealias Root = PropertyInjector<TargetType>

    func configure<B : Binder>(binder binder: B) {
        binder
            .bindPropertyInjectionOf(TargetType.self)
            .to(injector: TargetType.inject)
    }
}

Upvotes: 0

Related Questions