为什么 Swinject 模型 class 注册时没有“.inObjectScope(.Container)”产生单例?
Why is Swinject model class registered without ".inObjectScope( .Container )" producing a singleton?
这个问题是为 Swift 有很多 Swinject 经验的人准备的。
我会展示有问题的代码,我的问题在最下面。
代码有点多,不好意思。
这是MySwinjectStoryboard.swift
注册:
import Swinject
extension SwinjectStoryboard
{
class func setup ()
{
defaultContainer.register( Stopwatch.self )
{
responder in Stopwatch(
signals: responder.resolve( SignalsService.self )!
)
}
defaultContainer.register( SignalsService.self )
{
_ in SignalsService()
}.inObjectScope( .Container )
defaultContainer.register( ImageService.self )
{
responder in ImageService(
signals: responder.resolve( SignalsService.self )!
, stopwatch: responder.resolve( Stopwatch.self )!
)
}.inObjectScope( .Container )
defaultContainer.registerForStoryboard( StartUpViewController.self )
{
resolvable, viewController in
viewController.stopwatch = resolvable.resolve( Stopwatch.self )!
viewController.image = resolvable.resolve( ImageService.self )!
}
}
}
这是 Stopwatch.swift
,它只是在触发 onComplete 处理程序之前暂停了一会儿:
import Foundation
class Stopwatch: StopwatchProtocol
{
var key: String { return "Stopwatch_\( _key ).Complete" }
private var
_signals: SignalsProtocol
, _key: UInt16
, _timer: NSTimer?
, _data: AnyObject?
func startWith (
Delay delay: Double
, ForListener closure: ( String, Any? ) -> Void
){
_data = nil
_startWith( Delay: delay, ForListener: closure )
}
func stop ()
{
guard let timer = _timer else { return }
timer.invalidate()
_timer = nil
_data = nil
}
private func _startWith (
Delay delay: Double
, ForListener closure: ( String, Any? ) -> Void
){
stop()
_timer = NSTimer.scheduledTimerWithTimeInterval(
NSTimeInterval( delay )
, target: self
, selector: #selector( _onTimerComplete )
, userInfo: nil
, repeats: false
)
}
@objc private func _onTimerComplete ()
{
stop()
print( "stopwatch with key `\( key )` complete." )
}
required init ( signals: SignalsProtocol )
{
_signals = signals
_key = getPrimaryKey()
print( "primary key: \( _key )" )
}
}
ImageService.swift
目前仅通过 init
函数接受信号和秒表 属性:
protocol ImageProtocol {}
class ImageService: ImageProtocol
{
private let
_signals: SignalsProtocol
, _stopwatch: StopwatchProtocol
required init (
signals: SignalsProtocol
, stopwatch: StopwatchProtocol
){
_signals = signals
_stopwatch = stopwatch
lo( "ImageService key: \( _stopwatch.key )" )
}
}
SignalsService.swift
目前是一个空模型 class:
protocol SignalsProtocol {}
class SignalsService: SignalsProtocol {}
虽然 StartUpViewController.swift
是一个基本的 UIViewController
,目前只接受其注入的属性:
import UIKit
class StartUpViewController: UIViewController
{
var image: ImageService? {
willSet {
guard _image == nil else { return }
_image = newValue
}
}
var signals: SignalsService? {
willSet {
guard _signals == nil else { return }
_signals = newValue
}
}
var stopwatch: StopwatchProtocol? {
willSet {
guard _stopwatch == nil else { return }
_stopwatch = newValue
print( "StartUpViewController key: \( _stopwatch.key )" )
}
}
internal var
_image: ImageService!
, _signals: SignalsService!
, _stopwatch: Stopwatch!
}
最后 getPrivateKey()
只是一个全局静态,返回唯一的整数:
private var _primaryKey = UInt16( 0 )
func getPrimaryKey () -> UInt16
{
_primaryKey += 1
return _primaryKey
}
据我了解,我在 MySwinjectStoryboard.swift
中注册 Stopwatch.swift
的方式意味着每次注入实例时,它将是一个新的离散实例。但是,ImageService.swift
和 StartUpViewController.swift
都被注入了同一个实例:
StartUpViewController key: Stopwatch_2.Complete
ImageService key: Stopwatch_2.Complete
ImageService
的密钥应该是:
ImageService key: Stopwatch_3.Complete
请问有人知道为什么会这样吗?谢谢。
服务的默认范围是 .Graph
。来自 documentation:
With ObjectScope.Graph, an instance is always created, as in ObjectScope.None, if you directly call resolve method of a container, but instances resolved in factory closures are shared during the resolution of the root instance to construct the object graph.
如果您希望即使在对象图解析期间也为每个引用创建一个唯一实例,您应该使用对象范围 .None
,即
defaultContainer.register(Stopwatch.self) { resolver in
Stopwatch(signals: resolver.resolve(SignalsService.self)!)
}.inObjectScope(.None)
这个问题是为 Swift 有很多 Swinject 经验的人准备的。
我会展示有问题的代码,我的问题在最下面。
代码有点多,不好意思。
这是MySwinjectStoryboard.swift
注册:
import Swinject
extension SwinjectStoryboard
{
class func setup ()
{
defaultContainer.register( Stopwatch.self )
{
responder in Stopwatch(
signals: responder.resolve( SignalsService.self )!
)
}
defaultContainer.register( SignalsService.self )
{
_ in SignalsService()
}.inObjectScope( .Container )
defaultContainer.register( ImageService.self )
{
responder in ImageService(
signals: responder.resolve( SignalsService.self )!
, stopwatch: responder.resolve( Stopwatch.self )!
)
}.inObjectScope( .Container )
defaultContainer.registerForStoryboard( StartUpViewController.self )
{
resolvable, viewController in
viewController.stopwatch = resolvable.resolve( Stopwatch.self )!
viewController.image = resolvable.resolve( ImageService.self )!
}
}
}
这是 Stopwatch.swift
,它只是在触发 onComplete 处理程序之前暂停了一会儿:
import Foundation
class Stopwatch: StopwatchProtocol
{
var key: String { return "Stopwatch_\( _key ).Complete" }
private var
_signals: SignalsProtocol
, _key: UInt16
, _timer: NSTimer?
, _data: AnyObject?
func startWith (
Delay delay: Double
, ForListener closure: ( String, Any? ) -> Void
){
_data = nil
_startWith( Delay: delay, ForListener: closure )
}
func stop ()
{
guard let timer = _timer else { return }
timer.invalidate()
_timer = nil
_data = nil
}
private func _startWith (
Delay delay: Double
, ForListener closure: ( String, Any? ) -> Void
){
stop()
_timer = NSTimer.scheduledTimerWithTimeInterval(
NSTimeInterval( delay )
, target: self
, selector: #selector( _onTimerComplete )
, userInfo: nil
, repeats: false
)
}
@objc private func _onTimerComplete ()
{
stop()
print( "stopwatch with key `\( key )` complete." )
}
required init ( signals: SignalsProtocol )
{
_signals = signals
_key = getPrimaryKey()
print( "primary key: \( _key )" )
}
}
ImageService.swift
目前仅通过 init
函数接受信号和秒表 属性:
protocol ImageProtocol {}
class ImageService: ImageProtocol
{
private let
_signals: SignalsProtocol
, _stopwatch: StopwatchProtocol
required init (
signals: SignalsProtocol
, stopwatch: StopwatchProtocol
){
_signals = signals
_stopwatch = stopwatch
lo( "ImageService key: \( _stopwatch.key )" )
}
}
SignalsService.swift
目前是一个空模型 class:
protocol SignalsProtocol {}
class SignalsService: SignalsProtocol {}
虽然 StartUpViewController.swift
是一个基本的 UIViewController
,目前只接受其注入的属性:
import UIKit
class StartUpViewController: UIViewController
{
var image: ImageService? {
willSet {
guard _image == nil else { return }
_image = newValue
}
}
var signals: SignalsService? {
willSet {
guard _signals == nil else { return }
_signals = newValue
}
}
var stopwatch: StopwatchProtocol? {
willSet {
guard _stopwatch == nil else { return }
_stopwatch = newValue
print( "StartUpViewController key: \( _stopwatch.key )" )
}
}
internal var
_image: ImageService!
, _signals: SignalsService!
, _stopwatch: Stopwatch!
}
最后 getPrivateKey()
只是一个全局静态,返回唯一的整数:
private var _primaryKey = UInt16( 0 )
func getPrimaryKey () -> UInt16
{
_primaryKey += 1
return _primaryKey
}
据我了解,我在 MySwinjectStoryboard.swift
中注册 Stopwatch.swift
的方式意味着每次注入实例时,它将是一个新的离散实例。但是,ImageService.swift
和 StartUpViewController.swift
都被注入了同一个实例:
StartUpViewController key: Stopwatch_2.Complete
ImageService key: Stopwatch_2.Complete
ImageService
的密钥应该是:
ImageService key: Stopwatch_3.Complete
请问有人知道为什么会这样吗?谢谢。
服务的默认范围是 .Graph
。来自 documentation:
With ObjectScope.Graph, an instance is always created, as in ObjectScope.None, if you directly call resolve method of a container, but instances resolved in factory closures are shared during the resolution of the root instance to construct the object graph.
如果您希望即使在对象图解析期间也为每个引用创建一个唯一实例,您应该使用对象范围 .None
,即
defaultContainer.register(Stopwatch.self) { resolver in
Stopwatch(signals: resolver.resolve(SignalsService.self)!)
}.inObjectScope(.None)