Nic*_*der 40 uitableview ios swift xcode6
我想继承UITableViewController,并能够通过调用没有参数的默认初始化程序来实例化它.
class TestViewController: UITableViewController {
convenience init() {
self.init(style: UITableViewStyle.Plain)
}
}
Run Code Online (Sandbox Code Playgroud)
从Xcode 6 Beta 5开始,上面的示例不再有效.
Overriding declaration requires an 'override' keyword
Invalid redeclaration of 'init()'
Run Code Online (Sandbox Code Playgroud)
mat*_*att 61
注意此错误在iOS 9中已修复,因此整个问题在此时都没有实际意义.以下讨论仅适用于明确适应的特定系统和Swift版本.
这显然是一个错误,但也有一个非常简单的解决方案.我将解释问题,然后给出解决方案.请注意,我正在为Xcode 6.3.2和Swift 1.2写这个; 自从Swift首次问世以来,Apple已经在这方面全力以赴,因此其他版本的行为将有所不同.
您将手动实例化UITableViewController (即通过在代码中调用其初始化程序).并且您希望继承UITableViewController,因为您有要提供的实例属性.
所以,你从一个实例属性开始:
class MyTableViewController: UITableViewController {
let greeting : String
}
Run Code Online (Sandbox Code Playgroud)
这没有默认值,因此您必须编写初始值设定项:
class MyTableViewController: UITableViewController {
let greeting : String
init(greeting:String) {
self.greeting = greeting
}
}
Run Code Online (Sandbox Code Playgroud)
但那不是合法的初始化者 - 你必须打电话super
.比方说,您的来电super
是调用init(style:)
.
class MyTableViewController: UITableViewController {
let greeting : String
init(greeting:String) {
self.greeting = greeting
super.init(style: .Plain)
}
}
Run Code Online (Sandbox Code Playgroud)
但是你仍然无法编译,因为你需要实现init(coder:)
.所以你也是:
class MyTableViewController: UITableViewController {
let greeting : String
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
init(greeting:String) {
self.greeting = greeting
super.init(style: .Plain)
}
}
Run Code Online (Sandbox Code Playgroud)
您的代码现在编译!您现在很高兴(您认为)通过调用您编写的初始化程序来实例化此表视图控制器子类:
let tvc = MyTableViewController(greeting:"Hello there")
Run Code Online (Sandbox Code Playgroud)
在您运行应用程序之前,一切看起来都很快乐和美好,此时您会崩溃并显示以下消息:
致命错误:使用未实现的初始化程序
init(nibName:bundle:)
崩溃是由Cocoa中的一个错误引起的.你不知道,init(style:)
本身就叫init(nibName:bundle:)
.它打电话给它self
.那就是你 - MyTableViewController.但MyTableViewController没有实现init(nibName:bundle:)
.并且也不继承 init(nibName:bundle:)
,因为您已经提供了指定的初始化程序,从而切断了继承.
您唯一的解决方案就是实施 init(nibName:bundle:)
.但你不能,因为该实现需要你设置实例属性greeting
- 而你不知道要将它设置为什么.
简单的解决方案 - 几乎太简单,这就是为什么这么难以想到 - 是:不要继承UITableViewController.为什么这是合理的解决方案?因为你从来没有真正需要将它子类化.UITableViewController是一个毫无意义的类; 你不能为自己做任何事情.
所以,现在我们将把我们的类重写为UIViewController子类.我们仍然需要一个表视图作为我们的视图,因此我们将创建它loadView
,我们也将它连接在那里.更改标记为已加星标的评论:
class MyViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { // *
let greeting : String
weak var tableView : UITableView! // *
init(greeting:String) {
self.greeting = greeting
super.init(nibName:nil, bundle:nil) // *
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func loadView() { // *
self.view = UITableView(frame: CGRectZero, style: .Plain)
self.tableView = self.view as! UITableView
self.tableView.delegate = self
self.tableView.dataSource = self
}
}
Run Code Online (Sandbox Code Playgroud)
当然,您还需要添加最少的必需数据源方法.我们现在像这样实例化我们的类:
let tvc = MyViewController(greeting:"Hello there")
Run Code Online (Sandbox Code Playgroud)
我们的项目编译运行顺利进行.问题解决了!
你可能会反对说,如果不使用UITableViewController,我们就失去了从故事板中获取原型单元的能力.但这并不是反对意见,因为我们从一开始就没有这种能力.请记住,我们的假设是我们是子类并调用我们自己的子类的初始化器.如果我们从故事板中获取原型单元,故事板将通过调用实例化我们,init(coder:)
并且问题永远不会出现在第一位.
Nic*_*der 20
Xcode 6 Beta 5
看来你不能再为UITableViewController子类声明一个无参数的便利初始化器.相反,您需要覆盖默认初始值设定项.
class TestViewController: UITableViewController {
override init() {
// Overriding this method prevents other initializers from being inherited.
// The super implementation calls init:nibName:bundle:
// so we need to redeclare that initializer to prevent a runtime crash.
super.init(style: UITableViewStyle.Plain)
}
// This needs to be implemented (enforced by compiler).
required init(coder aDecoder: NSCoder!) {
// Or call super implementation
fatalError("NSCoding not supported")
}
// Need this to prevent runtime error:
// fatal error: use of unimplemented initializer 'init(nibName:bundle:)'
// for class 'TestViewController'
// I made this private since users should use the no-argument constructor.
private override init(nibName nibNameOrNil: String!, bundle nibBundleOrNil: NSBundle!) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
18792 次 |
最近记录: |