UIViewController的子类必须提供所需的初始化器'init(coder:)'。

4

我知道有其他类似的问题,但没有一个能回答下面我的问题。

所以我有一个ViewController,其布局在XIB中定义。从另一个ViewController中,我想做这样的事情:

let destVc = DestViewController(model:someModelData)
self.showViewController(destVc,...)

并且DestViewController定义如下:

class DestViewController : UITableViewController {
    var model: SomeModelData {
        didSet {
            self.tableView.reloadData()
        }
    }

    init(model: SomeModelData) {
        self.model = model
        super.init(style: .Plain)

    }

   //...implementation below
}

我之所以希望用这种方式实现是因为:
1)我不想为该视图控制器明确需要的模型数据使用可选或隐式解包的可选项,事实上,该模型数据是它的一部分。
2)这也带来了另一个好处,即将模型置于初始化程序中,为希望创建这些ViewControllers的任何人定义了一个清晰的契约,这得益于Swift强大的类型系统的支持。
问题是这不编译,Xcode显示:
 'required' initializer 'init(coder:)' must be provided by subclass of UIViewController

这真的很奇怪,因为在UIViewController的文档中,它没有将init(coder)声明为“required”初始化程序,它是指定的初始化程序,但在swift手册中没有任何地方说我必须重写指定的初始化程序,只有必需的初始化程序。

这里发生了什么,为什么我需要添加:

required init?(coder aDecoder: NSCoder) {

}

让它工作?

这是在 xcode 中 cmd 点击时出现的 UITableViewController 的 swift 文档,请注意 initWithCoder 前面的缺少 'required'。

public class UITableViewController : UIViewController, UITableViewDelegate, UIScrollViewDelegate, UITableViewDataSource {

    public init(style: UITableViewStyle)
    public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)
    public init?(coder aDecoder: NSCoder)

    public var tableView: UITableView!
    @available(iOS 3.2, *)
    public var clearsSelectionOnViewWillAppear: Bool // defaults to YES. If YES, any selection is cleared in viewWillAppear:

    @available(iOS 6.0, *)
    public var refreshControl: UIRefreshControl?
}
1个回答

7
如果您覆盖了类的任何“指定”初始化程序,虽然您不会继承任何其他指定的初始化程序。但是因为UIView采用了NSCoding协议,需要一个init(coder :)初始化程序。这就是为什么您需要实现init(coder :)的原因。
init(coder decoder: NSCoder) {
    super.init(coder: decoder)
}

NSCoding协议并没有要求这个初始化方法,如果我的父类已经提供了它,我为什么还需要实现它呢? - Luke De Feo
1
如果有一天有人派生你的类... 如果该类实例使用init(coder)进行初始化,编译器将执行层次结构。 - Mihir Mehta

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接