swift - 如何在 Swift 中子类化自定义 UIViewController?

标签 swift inheritance view uiviewcontroller subclassing

我想创建一个可重用的 View Controller UsersViewControllerBase

UsersViewControllerBase 扩展了 UIViewController,并实现了两个委托(delegate)(UITableViewDelegateUITableViewDataSource),并且有两个 View ( UITableView, UISegmentedControl)

目标是继承UsersViewControllerBase类的实现,在UsersViewController类中自定义分段控件的分段项。

class UsersViewControllerBase: UIViewController, UITableViewDelegate, UITableViewDataSource{
  @IBOutlet weak var segmentedControl: UISegmentedControl!
  @IBOutlet weak var tableView: UITableView!
  //implementation of delegates
}

class UsersViewController: UsersViewControllerBase {
}

UsersViewControllerBase 出现在故事​​板中,所有导出都已连接,标识符已指定。

问题是如何初始化 UsersViewController 以继承 UsersViewControllerBase 的所有 View 和功能

当我创建 UsersViewControllerBase 的实例时,一切正常

let usersViewControllerBase = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("UsersViewControllerBase") as? UsersViewControllerBase

但是当我创建 UsersViewController 的实例时,我得到了 nil outlets (我创建了一个简单的 UIViewController 并在 Storyboard 中为其分配了 UsersViewController 类)

let usersViewController = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("UsersViewController") as? UsersViewController

看起来 View 没有被继承。

我希望 UsersViewControllerBase 中的 init 方法能够从 Storyboard获取带有 View 和导出的 Controller :

  class UsersViewControllerBase: UIViewController, UITableViewDelegate, UITableViewDataSource{
      @IBOutlet weak var segmentedControl: UISegmentedControl!
      @IBOutlet weak var tableView: UITableView!
      init(){
        let usersViewControllerBase = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("UsersViewControllerBase") as? UsersViewControllerBase
        self = usersViewControllerBase //but that doesn't compile
      }
    }

然后我会初始化 UsersViewController:

let usersViewController = UsersViewController()

但不幸的是,这不起作用

最佳答案

当您通过instantiateViewControllerWithIdentifier 实例化 View Controller 时,过程基本上如下:

  • 它找到具有该标识符的场景;
  • 它确定该场景的基类;和
  • 它返回该类的一个实例。

然后,当您第一次访问 View 时,它将:

  • 创建 Storyboard场景中概述的 View 层次结构;和
  • 连接 socket 。

(这个过程实际上比这更复杂,但我试图将它简化为这个工作流程中的关键元素。)

此工作流的含义是导出和基类由您传递给 instantiateViewControllerWithIdentifier 的唯一 Storyboard 标识符确定。因此,对于基类的每个子类,您都需要一个单独的 Storyboard 场景,并将导出连接到该特定子类。

不过,有一种方法可以完成您的要求。您可以让 View Controller 实现 loadView(不要与 viewDidLoad 混淆)并让它以编程方式创建所需的 View 层次结构,而不是为 View Controller 使用 Storyboard场景由 View Controller 类。 Apple 曾经在他们的 iOS View Controller 编程指南 中很好地介绍了这个过程,但后来停止了该讨论,但仍然可以在他们的 legacy documentation 中找到它。 .

话虽如此,我个人不会被迫回到以编程方式创建 View 的旧世界,除非有非常令人信服的案例。我可能更倾向于放弃 View Controller 子类方法,并采用类似单个类的方法(这意味着我回到了 Storyboard的世界),然后将一些标识符传递给它,该标识符指示我希望从该特定实例获得的行为那一幕如果您想保持一些面向对象的优雅,您可以为数据源实例化自定义类,并根据您在此 View Controller 类中设置的某些属性进行委托(delegate)。

如果您需要真正动态的 View Controller 行为,而不是以编程方式创建的 View 层次结构,我会更倾向于走这条路。 或者,甚至更简单,继续采用您原来的 View Controller 子类化方法,并接受您需要在 Storyboard中为每个子类创建单独的场景。

关于swift - 如何在 Swift 中子类化自定义 UIViewController?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33809240/

相关文章:

java - 为什么在父方法中返回子类名?

c++ - 无法将继承的类作为 SFINAE 的基础

c++ - 这会导致内存泄漏吗/我应该如何构建代码

android - 如何在 Android 中动态设置 View 的位置?

swift - 快速更改父类(super class)属性类型

ios - 滚动到 collectionView 的底部不起作用

ios - 无法打开 Promise<[CLPlacemark]>

android - android中有定时器功能吗? (不是 java.util.Timer)

drupal 7显示当前用户的用户信息

swift - GPUImage2使用SolidColorGenerator作为矩形生成器