4

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

复制协议.swift:

protocol DuplicateProtocol { var id: String { get } }

SingletonProtocol.swift:

protocol SingletonProtocol { var id: String { get } }

复制代理.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。

4

1 回答 1

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 具有单例(又名容器)对象范围,可以按照.inObjectScope(.Container) 此处记录的方式进行设置。

更新 2

Swinject 0.3 版支持从“主”故事板隐式实例化 UIWindow 及其根视图控制器。这是它的文档

于 2015-10-08T11:57:05.313 回答