在另一个 class [Swift] 中访问视图控制器方法

Accessing view controller methods inside another class [Swift]

我通过在我的 ViewController (AnimalsVC) 中创建一个 UITableViewDiffableDataSource class 来为我的 tableview 的数据源使用 UITableViewDiffableDataSource。每当我尝试从我的数据源 class 中获取我的 ViewController 的数据数组(或任何其他 variables/functions)时,我都会收到此错误:

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

我不确定为什么会收到此错误,因为我的数据源 class 在我的 ViewController class 中。这是我的代码:

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
      }
   }

}

I am not sure why getting this error because my DataSource class is inside my ViewController class.

这没什么区别。在另一个 命名空间 内部声明一个 class 内部 class,即现在称为 AnimalsVC.DataSource。它不会导致内部 class 的一个实例能够神奇地看到外部 class 实例的内部(实际上我们完全不清楚我们将谈论的是什么实例)。 你嵌套的 class 声明是没有用的,所以你最好不要这样做。

相反,如果 DataSource 需要查看 AnimalsVC 内部,请执行您通常会做的事情:为您的 DataSource 实例提供对 AnimalsVC 实例的 引用

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

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

创建 DataSource 实例时,将其 vc 设置为 self。现在 DataSource 可以查询 AnimalsVC 实例的实例属性。

(实际上,我在自己的代码中所做的是给我的 UITableViewDiffableDataSource subclass 一个自定义指定的初始化程序。这样,我就可以创建数据源并将其传递给视图控制器的引用一招。)

为了从内部访问外部 class,您需要将引用传递给它。它不是自动的,例如 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
      }
   }

}

数据应包含在 DataSource class 中。将您的 animalsArray 移动到 DataSource class。

如果您需要从任何地方轻松访问它,请在 DataSource 下将其声明为:

static var animalsArray = [Animal]()

然后您可以使用 DataSource.animalsArray 从任何地方访问它,例如:

DataSource.animalsArray.append(animal)

我想您可以在 AnimalsVC 下将其创建为静态变量,但实际上应该在数据源中声明数据。

这将使您的 class 看起来像这样:

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
      }
   }
}

这是不可能的,因为。

"NestedTypes" it is not possible to access instance member or function in other class even Container class unlike "Inheritance" that you can access instance member or function of parent class.

如果您希望您的实施工作没有错误。 "Static" 会帮助你。

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 { [=10=].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.")
  }
}

测试。

let vc = AnimalVC()
vc.load()

嵌套类型

convenient to define utility classes and structures purely for use within the context of a more complex typequote

继承

Inherits characteristics from the existing class

来源