2017-02-21 25 views
1

我正在通過一本關於Swift的書,我理解函數中作用域的思想,所以接下來我要理解爲什麼我們在類中使用可選類型設置全局變量。說實話,看起來我們並沒有設置這些變量,而只是讓這個類知道整個代碼庫中會有一個特定類型的變量:var sut: ItemManager!瞭解swift中的可選全局變量

從我所瞭解的變量sut是一個類型ItemManger的解包可選項,它肯定具有有效值而不是零。我們將它設置爲感嘆號或問號的原因是因爲此類中沒有初始化程序。不清楚的是,因爲這個類沒有初始化程序,當決定使用問號標記或隱式地用感嘆號標記解釋天氣來將此全局變量設置爲可選時,哪些因素起作用?

import XCTest 
    @testable import ToDo 

    class ItemManagerTests: XCTestCase { 

     var sut: ItemManager! 

     override func setUp() { 
      super.setUp() 
      // Put setup code here. This method is called before the invocation of each test method in the class. 

      sut = ItemManager.init() 
     } 

     override func tearDown() { 
      // Put teardown code here. This method is called after the invocation of each test method in the class. 
      super.tearDown() 
     } 


     func test_ToDoCount_InitiallySetAtZero(){ 

      let sut = ItemManager.init() 

      XCTAssertEqual(sut.toDoCount, 0) 
     } 

     func test_DoneCount_InitiallySetAtZero(){ 

      let sut = ItemManager.init() 

      XCTAssertEqual(sut.doneCount, 0) 
     } 
    } 

回答

0

我們用感嘆號或問號設置它的原因是 ,因爲沒有這類

內的初始化因爲當一個類的每個實例初始化,它爲其屬性/實例var分配內存。所以var sut: ItemManager!,的值是nil,當init。如果沒有!,?編譯器無法分配init,所以您必須在初始化程序中手動初始化。這是編譯器告訴你的。

使用!?

  • !當屬性/ var在第一次賦值後總是有值時使用。並在第一時間它的分配之後,它不可能是零後
  • ?時使用PRO/VAR可以有值與否
+1

您列表中的第一項中沒有聲明是正確的。只要確保你不會沒有一個訪問它們了 - IUO到沒有價值這是完全正常的。 – Andreas

3

sut不是一個全局變量。

sut實例變量ItemManagerTests。每次實例化ItemManagerTests的新實例(即對象)時,都會爲sut分配內存。

它是ItemManager!類型。這是一個隱含的解包可選項。它類似於ItemManager?(也稱爲可選),區別在於它直接使用的地方被強制性地解開,就好像使用了力解包操作符(!)。

其值初始化爲nil,而是被設置爲一個新ItemManager對象時setUp由Xcode的測試框架調用。

3

首先,sut不是全局。 Swift中的全局變量在任何封閉範圍之外聲明(因此,在class聲明之前)。 sut是一個實例屬性; ItemManagerTests類的每個實例都將具有sut屬性。

在Swift中,所有非可選屬性必須在初始化完成時初始化。在某些情況下,這可以通過初始化程序中的代碼來實現,在其他情況下可以通過分配默認值來實現。

在某些情況下,S您不能分配或不願指定一個默認值,你不能(或不願)覆蓋初始化器。

如果你使用一個正常的可選那麼編譯器會信納該財產不被默認或初始化器初始化,但每次你提到的財產時,你就必須解開它(例如sut?.donecount)。

因爲你的測試用例在setup值分配給sut,你知道,這將有一個值,你可以使用武力展開(如sut!.donecount),或者,把它一步,使用隱式展開可選。這使您可以參考物業沒有任何解包,但它仍然是一個可選的,仍然會導致崩潰,如果它是nil。您當前的代碼甚至沒有使用屬性,因爲你是在分配你的測試用例的局部變量

注意。您可以使用:

class ItemManagerTests: XCTestCase { 

    var sut: ItemManager! 

    override func setUp() { 
     super.setUp() 
     // Put setup code here. This method is called before the invocation of each test method in the class. 

     sut = ItemManager.init() 
    } 

    override func tearDown() { 
     // Put teardown code here. This method is called after the invocation of each test method in the class. 
     super.tearDown() 
    } 

    func test_ToDoCount_InitiallySetAtZero() { 

     XCTAssertEqual(sut.toDoCount, 0) 
    } 

    func test_DoneCount_InitiallySetAtZero() { 

     XCTAssertEqual(sut.doneCount, 0) 
    } 
}