The Mother of Joseph Beuys The Mother of Joseph Beuys - 1 month ago 11
Swift Question

Dependency injection inconsistency in differing ViewControllers in Swinject, post Swift 3.0 update: why?

I am registering some

Swinject
singleton-with-a-small-s (.container) services thus:

defaultContainer.register( SomeService.self )
{
_ in SomeService()
}.inObjectScope( .container )

defaultContainer.register( AnotherService.self )
{
responder in AnotherService(
someService: responder.resolve( SomeService.self )!
)
}.inObjectScope( .container )


Injecting them into some view controllers thus:

defaultContainer.registerForStoryboard( SomeViewController.self )
{
resolvable, viewController in
viewController.someService = resolvable.resolve( SomeService.self )
viewController.anotherService = resolvable.resolve( AnotherService.self )!
}

defaultContainer.registerForStoryboard( AnotherViewController.self )
{
resolvable, viewController in
viewController.someService = resolvable.resolve( SomeService.self )
viewController.anotherService = resolvable.resolve( AnotherService.self )!
}


These view controllers are then being displayed in two different ways,
SomeViewController
like this:

DispatchQueue.main.async
{
self.performSegue( withIdentifier: "somePageSegue", sender: nil )
}


And
AnotherViewController
like this:

let anotherViewController = UIStoryboard(
name: "Main"
, bundle: nil
).instantiateViewController( withIdentifier: "anotherSegue" )

present( anotherViewController, animated: true, completion: nil )


SomeViewController
gets its services injected, but unfortunately
AnotherViewController
does not.

This used to work prior to
Swinject
's upgrade to Swift 3.0, but does not now. Why is this, and what needs to be changed, please?

Thank you.

UPDATE

I have neither the familiarity with
Swinject
's underlying code base nor the time to familiarize myself unfortunately, but digging around with what is happening under the surface I have discovered the following, which is hopefully useful to anyone who might know it better than I:

SUCCESSFUL VC DI:

// once into:
private func injectDependency(to viewController: UIViewController)

// then:
defaultContainer.registerForStoryboard( SomeViewController.self )

// then many times into:
public func _resolve<Service, Factory>(name: String?, option: ServiceKeyOptionType? = nil, invoker: (Factory) -> Service) -> Service?


FAILED VC DI:

// repeatedly going from:
private func injectDependency(to viewController: UIViewController)

// to:
public func _resolve<Service, Factory>(name: String?, option: ServiceKeyOptionType? = nil, invoker: (Factory) -> Service) -> Service?

// and back again,
// then twice into:
public override func instantiateViewController(withIdentifier identifier: String) -> UIViewController


ADDITIONAL NOTES:

The failing VC is a UIViewController within a TabBarController, both of which are already laid out in a standard XCode storyboard.

Answer

It turns out this is a bug, detailed here: https://github.com/Swinject/Swinject/issues/177. A fix is currently being worked on. I will report back once I know more.

UPDATE

This is apparently fixed.