0

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

Angad
  • 2,803
  • 3
  • 32
  • 45
  • Wouldn't this be a question for the Cleanse developers? – matt Jun 25 '16 at 05:09
  • @matt have proposed a new tag just in case - but `CleanseInjectable` is my protocol (not the framework's)! It seems Swift can't find the method signature I'm guaranteeing in the protocol – Angad Jun 25 '16 at 05:10
  • What I mean is, shouldn't you inquire thru the Issues page on github? This thing is a total beta, isn't it? – matt Jun 25 '16 at 05:13
  • @matt Will create an issue now - I can swear this is a Swift issue (at least at this point - it is possible I may stumble into a Cleanse limitation later on down this road). Was going to de-Cleansify this question before posting it here, but thought it may help to give exact code. Look at how Xcode is forcing me to `as!` `TargetType.self` into `CleanseInjectable.Type`, even though `TargetType` clearly guarantees to implement `CleanseInjectable`. It just seems weird – Angad Jun 25 '16 at 05:17

1 Answers1

0

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)
    }
}
Angad
  • 2,803
  • 3
  • 32
  • 45