ios init coder aDecoder 到底是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38386339/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 09:41:52  来源:igfitidea点击:

What exactly is init coder aDecoder?

iosswift

提问by JasonP

I'm learning iOS development from an online course and everytime I make a custom view (custom table view cell, collection view cell, etc) the instructor always implements this initializer:

我正在从在线课程中学习 iOS 开发,每次我制作自定义视图(自定义表格视图单元格、集合视图单元格等)时,讲师总是实现这个初始化程序:

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

Why exactly do I always have to call this? What does it do? Can I put properties inside the init?

为什么我总是要调用它?它有什么作用?我可以将属性放在 init 中吗?

回答by Code Different

I'll start this answer from the opposite direction: what if you want to save the state of your view to disk? This is known as serialization. The reverse is deserialization- restoring the state of the object from disk.

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

The NSCodingprotocol defines two methods to serialize and deserialize objects:

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

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

init(coder aDecoder: NSCoder) {
    // Deserialize your object here
}

So why is it needed in your custom class? The answer is Interface Builder. When you drag an object onto a storyboard and configure it, Interface Builder serializes the state of that object on to disk, then deserializes it when the storyboard appears on screen. You need to tell Interface Builder how to do those. At the very least, if you don't add any new properties to your subclass, you can simply ask the superclass to do the packing and unpacking for you, hence the super.init(coder: aDecoder)call. If your subclass is more complex, you need to add your own serialization and deserialization code for the subclass.

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

This is in contrast to the Visual Studio's approach, which is to write code into a hidden file to make the object at run time.

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

回答by Alexander - Reinstate Monica

The requirement to implement that initializer is a consequence of two things:

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

  1. The Liskov substitution principle. If S is a subclass of T (e.g. MyViewControlleris a subclass of ViewController), then S objects (instances of MyViewController) must be able to be substituted in where T objects (instances of ViewController) are expected.

  2. Initializers are not inherited in Swift if any initializers are explicitly defined in the subclass. If one initializer is explicitly provided, then all others must be explicitly provided (which can then just call super.init(...)). See this questionfor rationale. It's in Java, but still applies.

  1. 里氏替换原则。如果 S 是 T 的子类(例如,MyViewController是 的子类ViewController),则 S 对象( 的实例MyViewController)必须能够被替换为 T 对象( 的实例ViewController)。

  2. 如果在子类中显式定义了任何初始化器,则 Swift 中不会继承初始化器。如果显式提供了一个构造器,则必须显式提供所有其他构造器(然后可以调用super.init(...))。请参阅此问题以了解基本原理。它在 Java 中,但仍然适用。

By point 1, everything the original ViewControllercan do, the MyViewControllersubclass should be able to do. One such thing is to be able to be initialized from a given NSCoder. By point 2, your MyViewControllersubclass doesn't automatically inherit this ability. Thus, you must manually supply the initializer that fulfills this requirement. In this case, you just need to delegate up to the superclass, to have it do what it would usually do.

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