DI
Swift
Swinject
swift4

Swift 4でSwinjectStoryboardを使ったDIができない時の解決法

エラーの概要

Swinject/SwinjectStoryboardを使ってViewControllerにViewModelをDIしようとしたのですが、Xcode 9・Swift 4環境下では上手くDIできず、ViewModelインスタンスの値がnilになってしまいました。。。

SwinjectStoryboard+Setup.swift
import SwinjectStoryboard

extension SwinjectStoryboard {

    class func setup() {

        defaultContainer.register(HogeViewModel.self) { _ in
            HogeViewModel()
        }

        defaultContainer.storyboardInitCompleted(HogeViewController.self) { (r, c) in
            c.viewModel = r.resolve(HogeViewModel.self)
        }
    }
}

HogeViewModel.swift
class HogeViewModel {
    func foo() {
        print("foo")
    }
}

HogeViewController.swift
import UIKit

class HogeViewController: UIViewController {

    var viewModel: HogeViewModel!

    override func viewDidLoad() {
        super.viewDidLoad()

        viewModel.foo()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }


}

実行すると

picture1.png

値がnilになっている。。。

エラーの解決法

こちらのIssueを発見し、もう一度READMEをよく読むと以下の一文が。。。

Note that @objc attribute is mandatory here in swift 4.

これに従ってsetup()の頭に@objcをつけると

SwinjectStoryboard+Setup.swift
import SwinjectStoryboard

extension SwinjectStoryboard {

    @objc class func setup() {

        defaultContainer.register(HogeViewModel.self) { _ in
            HogeViewModel()
        }

        defaultContainer.storyboardInitCompleted(HogeViewController.self) { (r, c) in
            c.viewModel = r.resolve(HogeViewModel.self)
        }
    }
}

picture2.png

無事にDIできました!

参考

https://github.com/Swinject/SwinjectStoryboard
https://github.com/Swinject/SwinjectStoryboard/issues/72