SwinjectStoryaboard+Assembler, VC instantiated via Storyboard: injected properties are nil

Created on 8 Sep 2016  路  2Comments  路  Source: Swinject/Swinject

Info:

Swinject 2.0.0-beta.1
SwinjectStoryboard 1.0.0-beta.1

I have created assemblies like so:

class SwinjectManagerAssembly: AssemblyType {

    func assemble(container: Container) {

        container.register(Networkable.self) { _ in
            NetworkManager()
        }.inObjectScope(.Hierarchy)

        container.register(Bluetoothable.self) { _ in
            BluetoothManager()
        }.inObjectScope(.Hierarchy)

        container.register(Databaseable.self) { _ in
            DatabaseManager()
        }.inObjectScope(.Hierarchy)
    }

}

class SwinjectServiceAssembly: AssemblyType {

    func assemble(container: Container) {

        container.register(APIFetcherServiceType.self) { r in
            APIFetcher(networkManager: r.resolve(Networkable.self)!, databaseManager: r.resolve(Databaseable)!)
            }.inObjectScope(.Hierarchy)

    }

}

class SwinjectViewModelAssembly: AssemblyType {

    func assemble(container: Container) {
        container.register(MainViewModel.self) { r in
            MainViewModel(apiFetcher: r.resolve(APIFetcherServiceType)!)
        }.inObjectScope(.Hierarchy)
    }

}

class SwinjectViewControllerAssembly: AssemblyType {

    func assemble(container: Container) {

        container.registerForStoryboard(MainViewController.self, name: "Main") {r, c in
            c.viewModel = r.resolve(MainViewModel.self)
        }
    }

}

and then created an assembler class:

class SwinjectAssembler: BaseObject {

    private let assembler = try! Assembler(assemblies: [
        SwinjectManagerAssembly(),
        SwinjectServiceAssembly(),
        SwinjectViewModelAssembly(),
        SwinjectViewControllerAssembly()
        ], container: SwinjectStoryboard.defaultContainer)

    func mainViewController() -> MainViewController {
        let mainVC = SwinjectStoryboard.create(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("Main") as! MainViewController
        return mainVC
    }

    func apiFetcher() -> APIFetcherServiceType {
        return assembler.resolver.resolve(APIFetcherServiceType.self)!
    }

}

Now when I write this code:

private let appAssembler = SwinjectAssembler()
let apiFetcher = appAssembler.apiFetcher()
let mainVC = appAssembler.mainViewController()

apiFetcher got all properties injected properly, but mainVC's viewModel property is nil. It seems like the block in registerForStoryboard function from SwinjectViewControllerAssembly:

container.registerForStoryboard(MainViewController.self, name: "Main") {r, c in
            c.viewModel = r.resolve(MainViewModel.self)
        }

doesn't get called, but I don't know why. Am I doing something wrong?

question

Most helpful comment

Great, thanks!
Changing

container.registerForStoryboard(MainViewController.self, name: "Main") {r, c in
            c.viewModel = r.resolve(MainViewModel.self)
        }

to

container.registerForStoryboard(MainViewController.self) {r, c in
            c.viewModel = r.resolve(MainViewModel.self)
        }

fixed the issue. I must have missed that 馃憤

All 2 comments

I would suspect you don't have storyboard set up properly: name used during registerForStoryboard does not correspond to StoryboardID of a view controller, but to custom swinjectStoryboardName attribute (which is optional and useful if storyboard has more than one controller of given type).

For more info see documentation

Great, thanks!
Changing

container.registerForStoryboard(MainViewController.self, name: "Main") {r, c in
            c.viewModel = r.resolve(MainViewModel.self)
        }

to

container.registerForStoryboard(MainViewController.self) {r, c in
            c.viewModel = r.resolve(MainViewModel.self)
        }

fixed the issue. I must have missed that 馃憤

Was this page helpful?
0 / 5 - 0 ratings