【问题标题】:Accessing view controller methods inside another class [Swift]访问另一个类中的视图控制器方法 [Swift]
【发布时间】:2020-06-04 08:07:21
【问题描述】:

我通过在我的 ViewController (AnimalsVC) 中创建一个 UITableViewDiffableDataSource 类,将 UITableViewDiffableDataSource 用于我的 tableview 的数据源。每当我尝试从数据源类中获取 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
      }
   }

}

【问题讨论】:

    标签: ios swift uitableview datasource


    【解决方案1】:

    我不知道为什么会出现这个错误,因为我的 DataSource 类在我的 ViewController 类中。

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

    相反,如果 DataSource 需要查看 AnimalsVC 内部,请执行您通常会做的事情:给您的 DataSource 实例一个 reference 到 AnimalsVC 实例:

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

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

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        数据应包含在 DataSource 类中。将你的 animalsArray 移动到 DataSource 类中。

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

        static var animalsArray = [Animal]()
        

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

        DataSource.animalsArray.append(animal)
        

        我猜你可以在 AnimalsVC 下将它创建为静态变量,但数据确实应该在数据源中声明。

        这会让你的班级看起来像这样:

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

        【讨论】:

          【解决方案4】:

          这是不可能的,因为。

          “NestedTypes”无法访问实例成员或函数 在其他类中,甚至 Container 类与“继承”不同,您可以 访问父类的实例成员或函数。

          如果您希望您的实施工作没有错误。 “静态”会帮助你。

          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.")
            }
          }
          

          测试。

          let vc = AnimalVC()
          vc.load()
          

          嵌套类型

          方便定义实用程序类和结构,纯粹用于更复杂的类型引用的上下文中

          继承

          继承现有类的特征

          来源

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-06-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-01-21
            • 2015-08-02
            相关资源
            最近更新 更多