什么时候在 UIView 或 UIViewController 上调用“required init?(coder aDecoder: NSCoder)”?

Posted

技术标签:

【中文标题】什么时候在 UIView 或 UIViewController 上调用“required init?(coder aDecoder: NSCoder)”?【英文标题】:When is "required init?(coder aDecoder: NSCoder)" called on a UIView or UIViewController? 【发布时间】:2018-09-08 21:28:50 【问题描述】:

当我使用存储属性创建UIViewUIViewController 的子类时,除非我包含required init?(coder aDecoder: NSCoder) 的实现,否则Xcode 不会编译我的项目。目前,我有以下实现来关闭编译器:

required init?(coder aDecoder: NSCoder) 
    fatalError()

我明白为什么我需要包含这个初始化程序;我的子类需要符合NSCoding 协议,因为它的超类符合它,并且这个初始化程序是NSCoding 协议的一部分,因此它需要与我的类一起使用,即初始化我类的所有存储属性(超类初始化程序的版本不会这样做)。

我想一个正确的实现应该是这样的:

class MyView: UIView 
    let label: UILabel

    override init(frame: CGRect) 
        label = UILabel()
        super.init(frame: frame)
    

    required init?(coder aDecoder: NSCoder) 
        if let label = aDecoder.decodeObject() as? UILabel 
            self.label = label
         else 
            return nil
        
        super.init(coder: aDecoder)
    

    override func encode(with aCoder: NSCoder) 
        aCoder.encode(label)
        super.encode(with: aCoder)
    

但是,考虑到我的应用程序有超过 50 个自定义视图和视图控制器,在每个自定义视图和视图控制器中正确实现此功能需要大量工作。

所以,我想知道是否有必要正确实现这个初始化程序,或者我是否可以让它抛出一个致命错误。换句话说,如果我不在自己的代码中调用这个初始化程序,它会被调用吗?我想我读到它可能会被 Storyboard 调用,但我的应用程序不使用任何故事板。

【问题讨论】:

如果您的视图实例用于情节提要场景或 xib 文件中,则将调用此初始化程序。 @Paulw11,您应该将其发布为答案。 【参考方案1】:

如果您的视图实例在情节提要场景中使用,则将调用此初始化程序。

是否创建有效的初始化程序取决于您,但主要是从init(frame:)复制代码

【讨论】:

好的。作为对此的后续行动,如果我选择不制作功能初始化程序,是否有比仅仅抛出致命错误更好的方法来标记它? IE。一种标记它的方法,如果有人试图从代码中调用它会导致编译器错误,而不是运行时错误? 不,你可以调用致命错误或者你可以返回nil,因为它是一个失败的初始化器。 NSCoder 不是仅用于情节提要吗?我从未见过将它与 xibs 一起使用。 故事板基本上只是一堆带有一些附加信息的 Xib;在应用中使用时,没有太大区别。

以上是关于什么时候在 UIView 或 UIViewController 上调用“required init?(coder aDecoder: NSCoder)”?的主要内容,如果未能解决你的问题,请参考以下文章

我应该写啥完成处理程序?

UIView的frame,bounds,center,origin,啥时候用啥?

UIView 的 bounds.origin 啥时候不是 (0, 0)?

如何旋转 UIView?

将uiview分配或替换给其他uiview

子类化 UIView 或使用 UIView 组合