Swinject: Registering/resolving with argument for protocol/concrete value

Created on 7 Oct 2016  路  9Comments  路  Source: Swinject/Swinject

I have a class, let's call it SomeClass. It has an initializer that takes in a view controller; except I have added an arbitrary protocol that my view controllers implement to abstract things away so I can test SomeClass. So the initializer looks like:

init(viewController: ViewControllerType)

All my viewcontrollers implement ViewControllerType.

I want to register SomeClass with Swinject and then pass the view controller into it as an argument, so I did:

container.register(SomeClass.self) {
  r, viewController in
  return SomeClass(viewController: viewController)
}

Only, Swinject has taken the ViewControllerType and doesn't see that having been registered. It only sees concrete view controllers being registered I guess?

What I can do to fix this?

question

Most helpful comment

@siggb r.resolve(ProtocolOne.self, argument: model) is passing argument of type Hero?, while your register methods expecs argument of type Hero. One way to solve this would be

r.resolve(ProtocolOne.self, argument: model!)

All 9 comments

Hi @gbrhaz,
please add the code where you are resolveing SomeClass - It is hard to tell what exactly is the problem only from register method.
Thanks 馃槈

Sure:

container.registerForStoryboard(ConcreteViewController.self) {
  r, controller in

  controller.someClass = r.resolve(SomeClass.self, argument: controller)!
}

In this code compiler would be unable to infer the type of controller variable - you need to explicitly specify it, e.g.

container.register(ConcreteViewController.self) { (r, controller: ViewControllerType) in
  Controller(someClass: r.resolve(SomeClass.self, argument: controller)!
}

Seems to be inferring it just fine. The problem is a runtime issue, not a compiler issue.

@jakubvano Could you please help me understand my situation: I am not using storyboards and just trying to register some Service with argument. But resolve with argument always return nil.
This is a bug or I am just doing something wrong?
My code below:

// func assemble(container: Container)
var model: Hero?
container.register(ProtocolOne.self) { (r, hero: Hero) in
    model = hero
    let vc = ViewController(withHero: hero)
    let helper = r.resolve(ProtocolTwo.self)!
    vc.helper = helper
    return vc
}
container.register(ProtocolTwo.self) { _ in
    Helper()
}
.initCompleted { (r, two) in
    let helper = two as? Helper
    helper!.controller = r.resolve(ProtocolOne.self, argument: model) // always nil
}
// Usage:
assembler?.resolver.resolve(ProtocolOne.self, argument: Character(name: "Alex"))

@gbrhaz Sorry, I mistook registerForStoryboard for register method - A it stands, you need to explicitly upcast controller (for more info see docs):

controller.someClass = r.resolve(SomeClass.self, argument: controller as ViewControllerType)!

@siggb r.resolve(ProtocolOne.self, argument: model) is passing argument of type Hero?, while your register methods expecs argument of type Hero. One way to solve this would be

r.resolve(ProtocolOne.self, argument: model!)

@jakubvano That fixed it. Thanks, I did see something with the registration key, it just didn't click :)

Glad to help 馃槃 v1.1.5 will include logging of resolution failure (#168) which should help with debugging issues like these.

Was this page helpful?
0 / 5 - 0 ratings