我们都知道,只要将插座放到View或其ViewController中,它就会被标记为未包装,并且我们都知道Swift想要在初始化阶段初始化所有属性,这就是我们给任何问我们的人的一句话这是第一次为什么网点总是带有感叹号。
今天,我试图理解为什么不能在initWithCoder:
方法中初始化来自XIB的对象。
据我所知,XIB文件仅包含有关使用XML文件结构在XIB内部绘制的对象的所有信息。因此,我们将在XIB文件中看到的内容存档并存储到文件中。
当我们调用UINib
loadNibNamed:owner:options:
class方法时,它将取消存档先前创建的对象,查找所有属性,设置它们并将消息发送awakeFromNib
给该对象...
但是由于上面的感叹号是“在初始化阶段我无法初始化您”,因此我上面所说的应该是错误的。为什么?有人可以告诉我为什么Nib不能被初始化,应该标记为可选吗?
在这里,我有一些来自Apple的文档,对我没有帮助https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html
您的@IBOutlet
属性由UIViewController
子类引入。
说“ Swift希望在初始化阶段初始化所有属性”有点过于简化了。
Swift初始化规则指出,子类引入的所有属性必须在调用超类初始化程序之前进行初始化,并且Swift编译器必须能够“看到”该初始化;必须有一个明确的分配。这是“安全检查1”:-
安全检查1
指定的初始化程序在将其委托给超类初始化程序之前,必须确保初始化其类引入的所有属性。
在几乎所有使用XIB或情节提要场景的情况下,都不会覆盖init(coder:)
,因此编译器可以确定您没有为这些属性显式分配值。
如果您确实覆盖了初始化程序并分配了值(或者即使您在声明属性时只是分配了默认值),则可以将它们设置为常规属性,而不是隐式地展开可选属性,但这将是没有意义的,因为您几乎会立即覆盖加载XIB时的那些值。
一个隐式解包的可选内容不会说“在初始化阶段,我无法初始化您”;它更像是“我知道它似乎尚未初始化,但是在运行时它将是。相信我”(严格来说,它只是声明一个可选参数,允许使用nil
,因此编译器不会抱怨。它没有被初始化,而是在引用该属性时隐式强制打开该属性-因此,名称为“隐式展开可选”。
这适用于,@IBOutlet
因为加载过程使用键值编码在运行时分配值。
这就是为什么如果删除@IBOutlet
却忘记更新XIB / Storyboard的原因,则会得到运行时异常,指出您的类“不兼容xxx的键/值”。
通常认为以这种方式使用隐式解开的可选选项是可以接受的,因为您可以在测试过程中很快找出是否有连接问题(因为您的应用程序将崩溃并出现“意外的nil”),并且可以节省很多条件式解开。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句