Доступ к методам контроллера представления внутри другого класса [Swift] - PullRequest
0 голосов
/ 20 февраля 2020

Я использую UITableViewDiffableDataSource для источника данных моего табличного представления, создав класс UITableViewDiffableDataSource внутри моего ViewController (AnimalsV C). Всякий раз, когда я пытаюсь получить массив данных моего ViewController (или любые переменные / функции) из своего класса источника данных, я получаю эту ошибку:

Instance member 'animalsArray' of type 'AnimalsVC' cannot be used on an instance of nested type 'AnimalsVC.DataSource'

Я не уверен, почему получаю эту ошибку потому что мой класс DataSource находится внутри моего класса ViewController. Вот мой код:

class AnimalsVC: UIViewController {
   var animalsArray = []

   class DataSource: UITableViewDiffableDataSource<Int, Animal> {
      override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {

         let items = animalsArray //<- This is where the error occurs   

         return true
      }
   }

}

Ответы [ 4 ]

1 голос
/ 20 февраля 2020

Я не уверен, почему получаю эту ошибку, потому что мой класс DataSource находится внутри моего класса ViewController.

Это не имеет значения. Объявление одного класса внутри другого просто пространства имен внутреннего класса, то есть он теперь называется AnimalsVC.DataSource. Это не приводит к тому, что один экземпляр внутреннего класса может магически видеть внутри экземпляра внешний класс (и на самом деле совершенно неясно, о каких случаях мы будем говорить). Ваше вложение объявлений классов бесполезно, поэтому вы можете и не делать этого.

Вместо этого, если DataSource нужно видеть внутри AnimalsV C, делайте то, что вы обычно делаете: присвойте экземпляру DataSource ссылка на экземпляр AnimalsV C:

class AnimalsVC: UIViewController {
    var animalsArray = // ...
}

class DataSource: UITableViewDiffableDataSource<Int, Animal> {
    weak var vc : AnimalsVC?
    // ...
}

Когда вы создаете свой экземпляр DataSource, установите его vc в self. Теперь DataSource может обращаться к свойствам экземпляра экземпляра AnimalsV C.

(На самом деле, то, что я делаю в своем собственном коде, это даю моему подклассу UITableViewDiffableDataSource специальный назначенный инициализатор. Таким образом, я могу создавать данные источник и передать ему ссылку на контроллер представления за один ход.)

0 голосов
/ 03 мая 2020

Это невозможно, потому что.

"NestedTypes" невозможно получить доступ к члену экземпляра или функции в другом классе, даже в классе контейнера, в отличие от "Наследования", к которому вы можете получить доступ к члену экземпляра или функции родительский класс.

Если вы хотите, чтобы ваша реализация работала без ошибок. «Stati c» поможет вам.

struct Animal {
  var label: String
}

class AnimalVC {
  static var animals: [Animal] = []
  var dataSource = DataSource()

  class DataSource {
    func add(_ animal: Animal) {
      animals.append(animal)
    }
    func display() {
      print(animals.map { $0.label })
    }
    func remove(_ index: Int) -> String? {
      guard index < (animals.count - 1) else { return nil }
      return animals.remove(at: index).label
    }
  }

  func load() {
    dataSource.display()
    dataSource.add(Animal(label: "Dog"))
    dataSource.display()
    for i in ["Cat", "Fish", "Bird"] {
      dataSource.add(Animal(label: i))
    }
    dataSource.display()
    print(vc.dataSource.remove(AnimalVC.animals.count) ?? "Cannot delete.")
  }
}

Test.

let vc = AnimalVC()
vc.load()

NestedTypes

удобно определять служебные классы и структуры исключительно для использования в контексте более сложного цитирования типа

Наследование

Наследует характеристики из существующего класса

Источник

0 голосов
/ 01 мая 2020

Данные должны содержаться в классе DataSource. Переместите ваш animalsArray в класс DataSource.

Если вам нужен легкий доступ из любого места, объявите его в DataSource как:

static var animalsArray = [Animal]()

Затем вы можете получить к нему доступ из любого места, используя DataSource.animalsArray, например:

DataSource.animalsArray.append(animal)

Полагаю, вы могли бы создать его как stati c var в AnimalsV C, но данные действительно должны быть объявлены в источнике данных.

Это сделает ваш класс похожим на это:

class AnimalsVC: UIViewController {
   class DataSource: UITableViewDiffableDataSource<Int, Animal> {
    static var animalsArray = [Animal]()
    override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        let items = DataSource.animalsArray
        return true
      }
   }
}
0 голосов
/ 30 апреля 2020

Чтобы получить доступ к внешнему классу изнутри, вам нужно передать ссылку на него. Это не автомат c, как, например, Java.

Если предположить, что объект Animal определен в другом месте, то вы можете сделать следующее:

class AnimalsVC: UIViewController {
   var animalsArray = [] as [Animal]

   class DataSource: UITableViewDiffableDataSource<Int, Animal> {

      var myanimal:AnimalsVC

      init(animal: AnimalsVC){
          myanimal = animal
          super.init()
      }

      override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {

         let items = myanimal.animalsArray //<- This should not be an error any more   

         return true
      }
   }

}
...