2017-02-17 82 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不同实例和可以访问相同的项目。