2017-02-17 77 views
0

在閱讀了Swift文檔和各種在線教程之後,圍繞引用類型和值類型進行頭部封裝仍然有點困難。更好地理解Swift中的引用類型和值類型

我正在從Swift TDD書中學習一個教程來理解Swift中的OOP體系結構。本教程基於創建待辦事項列表應用程序。在本書的開頭,我們創建了一個類似於每個項目的結構。接下來,我們創建了一個名爲ItemManger的類來管理可以執行項目的數組,以及另一個用於執行項目檢查的數組。我可以理解這樣一個想法,即從一個結構中創建項目,因爲它的值類型每次創建一個新實例並且由一個類創建itemManager,因爲我們只需要一個itemManger來跟蹤項目。我提出的問題是,當我們在另一個類或視圖控制器內創建一個ItemManager類型的實例(這是一個類)時,它會引用我們之前創建的同一個類,以便我們能夠訪問做項目數組?

在本書出版之前,爲了跟蹤一個班級的變量,我假定我們必須將它們標記爲靜態。

這裏是itemManager類:

import Foundation 

class ItemManager { 

    var toDoCount: Int {return toDoItems.count } 

    var doneCount: Int {return doneItems.count } 

    private var toDoItems: [ToDoItem] = [] 

    private var doneItems: [ToDoItem] = [] 


    func add(item: ToDoItem) { 

     if !toDoItems.contains(item){ 
      toDoItems.append(item) 
     } 

    } 

    func checkItem(at index: Int) { 
     let item = toDoItems.remove(at: index) 
     doneItems.append(item) 
    } 

    func doneItem(at index: Int) -> ToDoItem{ 
     return doneItems[index] 
    } 

    func item(at index: Int) -> ToDoItem{ 
     return toDoItems[index] 
    } 

    func removeAll(){ 

     toDoItems.removeAll() 
     doneItems.removeAll() 
    } 

} 

這裏是我們創建ItemManager類型的實例變量其他類:

import UIKit 

enum Section: Int { 
    case toDo 
    case done 
} 

class ItemListDataProvider: NSObject, UITableViewDataSource, UITableViewDelegate { 

    var itemManager: ItemManager? 


    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 


     guard let itemManager = itemManager else{return 0} 

     guard let itemSection = Section(rawValue: section)else{ fatalError() } 

     let numberOfRows: Int 

     switch itemSection { 
     case .toDo: 
      numberOfRows = itemManager.toDoCount 
     case .done: 
      numberOfRows = itemManager.doneCount 
     } 

     return numberOfRows 
    } 

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 

     let cell = tableView.dequeueReusableCell(withIdentifier: "ItemCell", for: indexPath) as! ItemCell 

     guard let itemManager = itemManager else { fatalError() } 

     guard let section = Section(rawValue: indexPath.section) else { fatalError() } 

     let item: ToDoItem 

     switch section { 
     case .toDo: 
      item = itemManager.item(at: indexPath.row) 
     case .done: 
      item = itemManager.doneItem(at: indexPath.row) 
     } 

     cell.configCell(with: item) 

     return cell 
    } 

    func numberOfSections(in tableView: UITableView) -> Int { 
     return 2 
    } 
} 

回答

2

在您發佈的代碼,你創建ItemManager的實例。

這裏是我們創建ItemManager類型的實例變量其他類:

ItemListDataProvider可以有ItemManager但它不會創建一個。通過調用它創建一個類作品的一個實例的構造是這樣的:

// Creates an instance of ItemManager and assigns it to itemManager 
let itemManager = ItemManager() 

因爲你並沒有顯示在創建您的項目經理在哪裏,這個問題

將這個指的是同一類的,我們創建了在此之前,我們將能夠訪問待做項目數組?

無法真正回答。你在哪裏創建了一個ItemManager的實例,你用它做了什麼?

下面是一個例子:

let itemManagerA = ItemManager() 

let itemListDataProviderA() = ItemListDataProvider() 
itemListDataProviderA.itemManager = itemManagerA 

let itemListDataProviderB() = ItemListDataProvider() 
itemListDataProviderB.itemManager = itemManagerA 

在這個例子中兩者ItemListProvider■找相同ItemManager並因此可以訪問相同的項目陣列。

相反,如果你正在做的事情是這樣的:

let itemManagerA = ItemManager() 
let itemListDataProviderA() = ItemListDataProvider() 
itemListDataProviderA.itemManager = itemManagerA 

let itemManagerB = ItemManager() // <-- This creates a SECOND instance of ItemManager 
let itemListDataProviderB() = ItemListDataProvider() 
itemListDataProviderB.itemManager = itemManagerB // <-- We use the SECOND instance instead of the first one for itemListDataProviderB 

兩個ItemListProvider■找的ItemListProvider不同實例和可以訪問相同的項目。