我想创建一个可重用的 View Controller UsersViewControllerBase
。
UsersViewControllerBase
扩展了 UIViewController
,并实现了两个委托(delegate)(UITableViewDelegate
、UITableViewDataSource
),并且有两个 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/