我从在线课程学习iOS开发,每当我创建自定义视图(自定义表格视图单元格,集合视图单元格等)时,教师总是实现此初始化程序:
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
为什么我总是要打电话给这个?它有什么作用?我可以在init中放置属性吗?
答案 0 :(得分:89)
我将从相反的方向开始这个答案:如果你想将视图的状态保存到磁盘怎么办?这称为序列化。反之亦然反序列化 - 从磁盘恢复对象的状态。
NSCoding
协议定义了两种序列化和反序列化对象的方法:
encodeWithCoder(_ aCoder: NSCoder) {
// Serialize your object here
}
init(coder aDecoder: NSCoder) {
// Deserialize your object here
}
那为什么在你的自定义课程中需要它?答案是Interface Builder。将对象拖到故事板上并对其进行配置时,Interface Builder会将该对象的状态序列化到磁盘上,然后在故事板出现在屏幕上时对其进行反序列化。您需要告诉Interface Builder如何执行这些操作。至少,如果你没有向你的子类添加任何新属性,你可以简单地让超类为你做包装和解包,因此super.init(coder: aDecoder)
调用。如果您的子类更复杂,则需要为子类添加自己的序列化和反序列化代码。
这与Visual Studio的方法形成对比,Visual Studio的方法是将代码写入隐藏文件以在运行时生成对象。
答案 1 :(得分:22)
实现初始化程序的要求是两件事的结果:
Liskov substitution principle。如果S是T的子类(例如MyViewController
是ViewController
的子类),则S对象(MyViewController
的实例)必须能够在T对象的位置替换(实例ViewController
)是预期的。
如果在子类中显式定义了任何初始化程序,则不会在Swift中继承初始化程序。如果显式提供了一个初始值设定项,则必须显式提供所有其他初始值设定项(然后可以调用super.init(...)
)。有关基本原理,请参阅this question。它是用Java编写的,但仍然适用。
从第1点开始,原始ViewController
可以做的所有事情,MyViewController
子类应该能够做到。一个这样的事情是能够从给定的NSCoder
初始化。到第2点,您的MyViewController
子类不会自动继承此功能。因此,您必须手动提供满足此要求的初始化程序。在这种情况下,您只需要委托超类,让它做它通常会做的事情。