init编码器究竟是什么?

Jas*_*onP 103 ios swift

我正在从在线课程学习iOS开发,每当我创建自定义视图(自定义表格视图单元格,集合视图单元格等)时,教师总是实现此初始化程序:

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}
Run Code Online (Sandbox Code Playgroud)

为什么我总是要打电话给这个?它有什么作用?我可以在init中放置属性吗?

Cod*_*ent 96

我将从相反的方向开始这个答案:如果你想将视图的状态保存到磁盘怎么办?这称为序列化.反过来是反序列化 - 从磁盘恢复对象的状态.

NSCoding协议定义了两个序列化和反序列化对象的方法:

encodeWithCoder(_ aCoder: NSCoder) {
    // Serialize your object here
}

init(coder aDecoder: NSCoder) {
    // Deserialize your object here
}
Run Code Online (Sandbox Code Playgroud)

那么为什么在你的自定义课程中需要它呢?答案是Interface Builder.将对象拖到故事板上并对其进行配置时,Interface Builder会将该对象的状态序列化到磁盘上,然后在故事板出现在屏幕上时对其进行反序列化.您需要告诉Interface Builder如何执行这些操作.至少,如果你没有向你的子类添加任何新属性,你可以简单地让超类为你做包装和解包,因此super.init(coder: aDecoder)调用.如果您的子类更复杂,则需要为子类添加自己的序列化和反序列化代码.

这与Visual Studio的方法形成对比,后者是将代码写入隐藏文件以在运行时生成对象.

  • @Honey如果你想在Interface Builder中配置你的对象,那么`awakeFromNib`将不起作用.在**运行时**调用`awakeFromNib`.您在Interface Builder中执行的任何操作都是在**设计时**.将您在*设计时*中执行的操作带到*运行时*是`encodeWithCoder`(保存)和`init(编码器:)`(加载) (9认同)
  • @Honey如果你不使用Interface Builder来配置自定义类(即用代码编程),那么你可以在`awakeFromNib`或`initWIthFrame`中完成它. (3认同)

Ale*_*ica 25

实现该初始化程序的要求是两件事的结果:

  1. 里氏替换原则.如果S是T的子类(例如MyViewController是其子类ViewController),则S对象(实例MyViewController)必须能够在需要T对象(实例ViewController)的地方替换.

  2. 如果在子类中显式定义了任何初始值设定项,则不会在Swift中继承初始值设定项.如果显式提供了一个初始值设定项,则必须显式提供所有其他初始值设定项(然后可以调用super.init(...)).请参阅此问题以获取理由.它是Java,但仍然适用.

通过第1点,原始ViewController可以做的一切,MyViewController子类应该能够做到.一个这样的事情是能够从给定的初始化NSCoder.到第2点,您的MyViewController子类不会自动继承此功能.因此,您必须手动提供满足此要求的初始化程序.在这种情况下,您只需要委托超类,让它做它通常会做的事情.

  • 实际上,假设您没有在子类中提供任何自己的初始化器实现,则初始化器是在Swift中继承的。如果新定义的非继承属性具有默认值,则可以不用在子类中编写任何初始化程序,而直接继承所有超类的初始化程序即可。请参阅[此处](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-ID222) (2认同)