Jos*_*Mum 2 singleton ios swift swinject
这个问题是针对对Swinject for Swift有丰富经验的人。
我将展示有问题的代码,我的问题在底部。
代码有点多,抱歉。
这是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 )!
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是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 )" )
}
}
Run Code Online (Sandbox Code Playgroud)
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 )" )
}
}
Run Code Online (Sandbox Code Playgroud)
SignalsService.swift目前是一个空的 Model 类:
protocol SignalsProtocol {}
class SignalsService: SignalsProtocol {}
Run Code Online (Sandbox Code Playgroud)
WhileStartUpViewController.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!
}
Run Code Online (Sandbox Code Playgroud)
最后getPrivateKey()是一个全局静态,返回唯一的整数:
private var _primaryKey = UInt16( 0 )
func getPrimaryKey () -> UInt16
{
_primaryKey += 1
return _primaryKey
}
Run Code Online (Sandbox Code Playgroud)
现在,据我了解,我注册的方式Stopwatch.swift意味着MySwinjectStoryboard.swift每次注入实例时,它将是一个新的离散实例。但是, 和ImageService.swift都StartUpViewController.swift被注入同一个实例:
StartUpViewController key: Stopwatch_2.Complete
ImageService key: Stopwatch_2.Complete
Run Code Online (Sandbox Code Playgroud)
ImageService的关键应该是:
ImageService key: Stopwatch_3.Complete
Run Code Online (Sandbox Code Playgroud)
请问有人知道为什么会发生这种情况吗?谢谢。
服务的默认范围是.Graph. 来自文档:
对于 ObjectScope.Graph,如果直接调用容器的resolve方法,总是会创建一个实例,就像在ObjectScope.None中一样,但是在工厂闭包中解析的实例在解析根实例以构造对象图期间会共享。
如果您希望即使在对象图解析期间也为每个引用创建唯一的实例,则应该使用对象范围.None,即
defaultContainer.register(Stopwatch.self) { resolver in
Stopwatch(signals: resolver.resolve(SignalsService.self)!)
}.inObjectScope(.None)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3017 次 |
| 最近记录: |