使用 Swinject 将模型 class 实例注入 Swift 中的视图 class 实例
Using Swinject to inject a Model class instance into a View class instance in Swift
在 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。
如果您想从故事板实例化视图控制器,则初始化程序注入不可用,因为 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) Object Scope,可以用 .inObjectScope(.Container)
as documented here.
设置
更新 2
Swinject 版本 0.3 支持从 "Main" 故事板隐式实例化 UIWindow 及其根视图控制器。 Here is its documentation.
在 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。
如果您想从故事板实例化视图控制器,则初始化程序注入不可用,因为 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) Object Scope,可以用 .inObjectScope(.Container)
as documented here.
更新 2
Swinject 版本 0.3 支持从 "Main" 故事板隐式实例化 UIWindow 及其根视图控制器。 Here is its documentation.