2016-03-23 3 views
0

私を驚かせる奇妙なことがありました。私が紛失しているシンプルな「In Swift 2 we're always(または決して)this」のような感じですが、私はそれを見ることができません。脳のための私のユニットテストでスウィフト、シングルトン、関数を表す変数

class Brain: NSObject { 

    static var sharedInstance : Brain? 

    var languageLoadedAndReadyFunction = languageLoadedAndReadyImplementation 

    init() { 
     NSNotificationCenter.defaultCenter().addObserver(self, 
      selector: "languageLoadedAndReady", 
      name: Notifications.LanguageLoadedAndReady, 
      object: nil) 
    } 

    func languageLoadedAndReadyImplementation() { 

     print("Got language Ready notification") 
    } 

    func languageLoadedAndReady() { 

     self.languageLoadedAndReadyFunction(self)() 
    } 

    class func get() -> Brain! { 

     return sharedInstance 
    } 

    //... 

    class func reset() { 

     sharedInstance = Brain()   
    } 

    deinit() { 

     NSNotificationCenter.defaultCenter().removeObserver(self) 
    } 
} 

::私は「頭脳としての機能を定義するために必要な

func testBrainRegisterForNotificationWhenWakingUp() { 

    let expectation = expectationWithDescription("Function should be called when the notification is received") 

    var brain = Brain.get() 

    brain.languageLoadedAndReadyFunction = {brain ->() ->() in 
     { 

      expectation.fulfill() 

      Brain.reset() // <-- this sets sharedInstance to a new Brain 
     } 
    } 

    brain.startUp() // <-- this causes the languageLoadedAndReady event to arrive at the brain 

    waitForExpectationsWithTimeout(5) { 
     error in 
     if let error = error { 
      print("Error: \(error.localizedDescription)") 
     } 
    } 
} 

方法私は脳のクラスを持っている

は、シングルトンとして使用するためのもの - >() - >() "は面倒だと感じていますが、それは治療に効くようです。通知がいつ届いたかを私に見せてもらったので、テストによって、正しく動作していることを確認できました。 deinit()メソッドは、脳がリセットされた後に呼び出され、古い脳がROMメモリから削除されていることを示しています。

今日、私はTranslatorTests.swiftのためにいくつかの新しいテストを書いている:

func testTranslatorCanTranslate() { 

    let expectation = expectationWithDescription("Function should be called when the notification is received2") 

    var brain = Brain.get() 

    brain.languageLoadedAndReadyFunction = {brain ->() ->() in 
     { 

      expectation.fulfill() 

      Brain.reset() 

      print("first TranslatorTests") 
     } 
    } 

    brain.startUp() // <-- 'brain' is different here than in BrainTests.swift, causes 
        // the closure in BrainTests.swift to be called. 

    waitForExpectationsWithTimeout(5) { 
     error in 
     if let error = error { 
      print("Error: \(error.localizedDescription)") 
     } 
    } 

    translator.setActiveLanguage("en") 

    let resultString = translator.translate("about_title") 

    XCTAssertEqual(resultString, "About") 
} 

func testTranslatorCanTranslateSecondWord() { 

    let expectation = expectationWithDescription("Function should be called when the notification is received3") 

    let brain = Brain.get() 

    brain.languageLoadedAndReadyFunction = {brain ->() ->() in 
     { 

      expectation.fulfill() 

      Brain.reset() 

      print("second TranslatorTests") 
     } 
    } 

    brain.startUp() // <-- 'brain' is different here than in BrainTests.swift, causes 
        // the closure in BrainTests.swift to be called. 

    waitForExpectationsWithTimeout(5) { 
     error in 
     if let error = error { 
      print("Error: \(error.localizedDescription)") 
     } 
    } 

    translator.setActiveLanguage("en") 

    let resultString = translator.translate("actmon_ready") 

    XCTAssertEqual(resultString, "Ready to upload") 
} 

私がテストを実行すると、私が最も奇妙なエラーが発生します。BrainTests.swiftでの閉鎖はときTranslatorTestsと呼ばれています。迅速に実行されます。これにより、expectation.fulfill()メソッドが2回目に呼び出され、クラッシュが発生します。

ちなみに、クロージャの内側には「自己」はありませんが、コールスタックの1つ上のレベルになると、「自己」は前の脳のインスタンスを参照します。それは脳 - >() - >()の構文が問題であると私に信じさせます。

これは私の話です。 「脳」はそれぞれのクロージャの前に異なるアドレスを持っています。それは私にそれが別のインスタンスであることを示します。実際、古い脳はこの時点で再命名されているので、どのように呼び出すことができますか?

私は、インスタンスの変数に代入すると、このインスタンスに対して実行するクロージャに新しい関数を与えていることになります。

誰でもこのことを私に説明できますか?小さな言葉を使ってください。私はこのコードを書いたときより少し賢明ではない気がします。私の研究では

答えて

0

は、私が助けたこの二つの記事を偶然見つけ:呼び出しがある理由を私に説明して

http://oleb.net/blog/2014/07/swift-instance-methods-curried-functions/ https://devforums.apple.com/message/1008188#1008188

「{脳 - >() - >()内.. "。

私は私のコードで持っていた問題は、もちろん、インスタンス変数は、私のテストファイルでこのように宣言したことを

:私はBrain.resetを呼び出したとき

class BrainTests: XCTestCase { 

    var brain: Brain! 

    override func setUp() { 

     super.setUp() 
     brain = Brain.get() 
    } 

    override func tearDown() { 

     super.tearDown() 
     Brain.reset() 
    } 

    func testBrainExists() { 

     XCTAssertNotNil(brain) 
    } 

ので、()ドロップします古いシングルトンを作成して新しいシングルトンを作成すると、まだ元のシングルトンへのポインタがありました。

インスタンス変数を削除することで、脳が正常にリセットされ、コールバックが機能しました。私はすべてのテストに合格するために、必要に応じて各テストケースからコールバックを設定することができました。

うわー、これは卑劣なものでした!

関連する問題