2017-02-17 10 views
0

После прочтения документации Swift и различных онлайн-руководств, все еще немного сложно обернуть голову вокруг ссылочных типов по сравнению с типами значений.Лучшее понимание ссылок на типы значений в Swift

Я следую учебнику из книги Swift TDD, чтобы понять архитектуру ООП в Swift. Учебник основан на создании списка приложений. В начале книги мы создали структуру, похожую на каждый предмет. Затем мы создали класс под названием ItemManger для управления массивом, который содержит элементы, а другой массив - для проверки элементов. Я могу понять идею делать элементы из структуры, потому что это тип значения, который создает новый экземпляр каждый раз при его создании, а itemManager создается из класса, так как нам нужен только один элемент управления для отслеживания действий. Вопрос, который я придумал, - это когда мы создаем экземпляр типа 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 s имеют различные экземпляры ItemListProvider и сделать не иметь доступ к тем же пунктам.