使用Swinject将Model类实例注入Swift

时间:2015-10-08 08:41:36

标签: ios swift dependency-injection swinject

在Swift 2.0,单页面应用程序项目中,在XCode 7.0.1中,使用Swift依赖注入框架Swinject,我正在执行以下操作:

DuplicateProtocol.swift:

protocol DuplicateProtocol { var id: String { get } }

SingletonProtocol.swift:

protocol SingletonProtocol { var id: String { get } }

DuplicateProxy.swift

class DuplicateProxy: DuplicateProtocol {
    let id: String

    init ( id: String ) {
        self.id = "DuplicateProxy." + id
    }
}

SingletonProxy.swift:

class SingletonProxy: SingletonProtocol {
    let id: String

    init ( id: String ) {
        self.id = "SingletonProxy." + id
    }
}

ViewController.swift:

import UIKit

class ViewController: UIViewController
{
    var duplicate: DuplicateProtocol?
    var singleton: SingletonProtocol?

    required init? ( coder aDecoder: NSCoder ) {
        print( "ViewController.init?", duplicate, singleton )
        super.init( coder: aDecoder )
    }

    override func viewDidLoad () {
        print( "ViewController.viewDidLoad", duplicate, singleton )
        super.viewDidLoad()
    }
}

AppDelegate.swift:

import Swinject
import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate
{
    var window: UIWindow?

    func application ( application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]? ) -> Bool {

        let container = Container()
        let singleton = SingletonProxy( id: "first" )

        container.register( SingletonProtocol.self ) { _ in singleton }
        container.register( DuplicateProtocol.self ) { _ in DuplicateProxy( id: "second" ) }

        container.registerForStoryboard( ViewController.self ) {
            r, c in c.duplicate = r.resolve( DuplicateProtocol.self )
        }

        print( "AppDelegate.application" )

        return true
    }
}

这是我不幸得到的控制台日志:

ViewController.init? nil nil
AppDelegate.application
ViewController.viewDidLoad nil nil

尽可能简单地说:我需要做出哪些改变?谢谢你,JBM。

1 个答案:

答案 0 :(得分:3)

如果要从故事板中实例化视图控制器,则无法使用初始化程序注入,因为UIKit框架会调用init?(coder:)

相反,应该使用属性注入来从故事板中实例化它:

class SomeViewController: UIViewController {
    var duplicate: DuplicateProtocol?
    var singleton: SingletonProtocol?

    required init?(coder aDecoder: NSCoder)
    {
        super.init(coder: aDecoder)
    }
}

<强>更新

Swinject不支持UIWindow和初始视图控制器的隐式实例化。您需要显式实例化它们,如下例所示。

import Swinject
import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    var container: Container {
        let container = Container()
        let singleton = SingletonProxy( id: "first" )

        container.register( SingletonProtocol.self ) { _ in singleton }
        container.register( DuplicateProtocol.self ) { _ in DuplicateProxy( id: "second" ) }

        container.registerForStoryboard( ViewController.self ) {
            r, c in c.duplicate = r.resolve( DuplicateProtocol.self )
        }

        return container
    }

    func application ( application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]? ) -> Bool {
        let window = UIWindow(frame: UIScreen.mainScreen().bounds)
        window.makeKeyAndVisible()
        self.window = window

        let storyboard = SwinjectStoryboard.create(name: "Main", bundle: nil, container: container)
        window.rootViewController = storyboard.instantiateInitialViewController()

        return true
    }
}

顺便说一下,你不必自己处理单例实例。 Swinject具有Singleton(aka Container)对象范围,可以使用.inObjectScope(.Container) as documented here进行设置。

更新2

Swinject版本0.3支持UIWindow及其根视图控制器的隐式实例化,来自&#34; Main&#34;故事板。 Here is its documentation