2016-09-22 7 views
1

この質問はSwiftの経験が豊富な方のためのものです。SwinjectSwinjectモデルクラスが ".inObjectScope(.Container)"なしでシングルトンを生成する理由は何ですか?

私は問題のあるコードを表示し、私の質問は下にあります。

かなりのコードがあります。申し訳ありません。

これは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)! 
     } 
    } 
} 

これは単にonCompleteのハンドラを発射する前にしばらく一時停止され、Stopwatch.swift次のとおりです。

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)") 
    } 
} 
ユニークな帰国、単にグローバル静的

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()さ:StartUpViewController.swiftながら

protocol SignalsProtocol {} 

class SignalsService: SignalsProtocol {} 

は現在、ちょうどその注入されたプロパティを受け入れる基本UIViewControllerです:

は現在空モデルクラスですインサート:

private var _primaryKey = UInt16(0) 

func getPrimaryKey() -> UInt16 
{ 
    _primaryKey += 1 
    return _primaryKey 
} 

今私が理解しているように、Stopwatch.swiftMySwinjectStoryboard.swiftに登録すると、インスタンスが挿入されるたびに新しい離散インスタンスになります。しかし、ImageService.swiftStartUpViewController.swiftの両方が同じインスタンスを注入されています:

StartUpViewController key: Stopwatch_2.Complete 
ImageService key: Stopwatch_2.Complete 

ImageServiceのキーがあるべき:なぜこれが起こっている

ImageService key: Stopwatch_3.Complete 

誰もが、してください知っていますか?ありがとうございました。

答えて

3

サービスのデフォルトスコープは.Graphです。 documentationから:あなたが直接コンテナのresolveメソッドを呼び出す場合

ObjectScope.Graphでは、インスタンスは常に、ObjectScope.Noneのように、作成されますが、工場閉鎖で解決インスタンスは、ルートの解像度の間に共有されていますインスタンスを使用してオブジェクトグラフを作成します。

あなたも、オブジェクトグラフの解決時に各参照用に作成される一意のインスタンスをしたい場合は、あなたがオブジェクトスコープ.Noneを使用する必要があり、すなわち

defaultContainer.register(Stopwatch.self) { resolver in 
    Stopwatch(signals: resolver.resolve(SignalsService.self)!) 
}.inObjectScope(.None) 
+0

はあなたにヤコブをありがとう! –

関連する問題