Ale*_*xey 11 inheritance view uiviewcontroller subclassing swift
我想创建一个可重用的视图控制器UsersViewControllerBase.
UsersViewControllerBaseextends UIViewController,并实现两个委托(UITableViewDelegate,UITableViewDataSource),并有两个视图(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 {
}
Run Code Online (Sandbox Code Playgroud)
的UsersViewControllerBase存在于故事板和所有出口连接,被指定的标识符.
问题是我如何初始化UsersViewController以继承所有的视图和功能 UsersViewControllerBase
当我创建UsersViewControllerBase一切工作的实例时
let usersViewControllerBase = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("UsersViewControllerBase") as? UsersViewControllerBase
Run Code Online (Sandbox Code Playgroud)
但是当我创建UsersViewController我获得插件的实例时nil(我创建了一个简单的UIViewController并在故事板中为其分配了UsersViewController类)
let usersViewController = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("UsersViewController") as? UsersViewController
Run Code Online (Sandbox Code Playgroud)
看起来不会继承视图.
我希望init方法UsersViewControllerBase可以从storyboard获取带有视图和出口的控制器:
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
}
}
Run Code Online (Sandbox Code Playgroud)
我会初衷UsersViewController:
let usersViewController = UsersViewController()
Run Code Online (Sandbox Code Playgroud)
但不幸的是,这不起作用
通过实例化视图控制器时instantiateViewControllerWithIdentifier,该过程基本上如下:
然后,当您第一次访问时view,它将:
(这个过程实际上比这更复杂,但我正在尝试将其减少到此工作流程中的关键元素.)
此工作流程的含义是,出口和基类由您传递给的唯一故事板标识符确定instantiateViewControllerWithIdentifier.因此,对于基类的每个子类,您需要一个单独的故事板场景,并将出口连接到该特定子类.
但是,有一种方法可以满足您的要求.您可以改为使视图控制器实现loadView(不要混淆viewDidLoad),而是以编程方式创建视图控制器类所需的视图层次结构,而不是将视图控制器用于故事板场景.Apple过去曾在他们的View Controller编程指南中对这个过程有一个很好的介绍,但是已经退出讨论,但它仍然可以在他们的遗留文档中找到.
话虽如此,我个人不会被迫回到以编程方式创建的视图的旧世界,除非有一个非常有说服力的案例.我可能更倾向于放弃视图控制器子类方法,并采用类似单个类的东西(这意味着我回到故事板的世界中),然后传递一些标识符,该标识符指示我想要的特定实例的行为那个场景.如果您希望保持一些OO优雅,可以根据您在此视图控制器类中设置的某些属性,为数据源和委托实例化自定义类.
如果你需要真正的动态视图控制器行为,而不是以编程方式创建的视图层次结构,我会更倾向于走这条路.或者,甚至更简单,继续采用原始视图控制器子类化方法,并接受在每个子类的故事板中需要单独的场景.
所以,你有你的基类:
class UsersViewControllerBase: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var segmentedControl: UISegmentedControl!
@IBOutlet weak var tableView: UITableView!
//implementation of delegates
}
Run Code Online (Sandbox Code Playgroud)
而你的子类:
class UsersViewController: UsersViewControllerBase {
var text = "Hello!"
}
Run Code Online (Sandbox Code Playgroud)
要正确使用子类,您需要这样做(类似):
class TestViewController: UIViewController {
...
func doSomething() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
//Instantiate as base
let usersViewController = storyboard.instantiateViewControllerWithIdentifier("UsersViewControllerBase") as! UsersViewControllerBase
//Replace the class with the desired subclass
object_setClass(usersViewController, UsersViewController.self)
//But you also need to access the instance variable 'text', so:
let subclassObject = usersViewController as! UsersViewController
subclassObject.text = "Hello! World."
//Use UsersViewController object as desired. For example:
navigationController?.pushViewController(subclassObject, animated: true)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6483 次 |
| 最近记录: |