覆盖init和所需的init之间的区别? - 迅速

时间:2017-10-25 07:50:30

标签: ios swift

我有时会看到这样的视图,在两个不同的init方法中有相同的setup()函数。 init方法之间有什么区别,为什么在两个中调用相同的setup()?

class BigButton: UIButton {

    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }

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

    fileprivate func setup() {
        // set up stuff
    }
}

3 个答案:

答案 0 :(得分:10)

以编程方式创建视图(在本例中为按钮)时使用

override init(frame: CGRect)

从storyboard / xib创建视图时使用

required init?(coder: NSCoder)

因为后者是必需的,你必须实现它的身体。但是,如果您不打算手动创建按钮,则不需要第一个按钮,可以省略

在两者中调用安装程序,因为无论您选择创建按钮,都要设置其自定义行为,以便按预期方式工作

答案 1 :(得分:4)

override初始值设定项(例如init(frame: CGRect))时,您可以针对指定的初始值设定项执行此操作,即负责以编程方式创建对象的主体初始值设定项。根据规则,您必须在执行任何其他初始化操作之前致电super.init

另一方面,所需的初始化程序与指定的不同。

  

必需的初始化程序

     

在定义类之前编写必需的修饰符   初始化程序,表示该类的每个子类都必须   实现初始化程序。

     

您还必须在每个子类之前编写必需的修饰符   执行一个必需的初始化程序,以表示该   初始化程序要求适用于链中的其他子类。   覆盖必需时,不要写覆盖修饰符   指定的初始化程序。

     

来源Apple Documentation On Initializers

如果原始类具有标记为必需的初始化程序,则在创建子类时,无论您的意愿如何,都可以实现所需的初始化程序。通常,您不应该直接调用它来创建对象,尽管在某些情况下您可以这样做。标记为必需的初始化程序,以符合若干要求。例如, 在几种情况下调用required init?(coder: NSCoder)。一种情况:视图是从IB创建的。另一种情况 - 手动创建对象时,或者更确切地说,取消归档(称为反序列化)。实际上,当您将该对象放在ViewController的视图上时(例如),该对象也 unarchived ,即加载并设置其所有属性。

显然,当您创建某个视图的子类时,您应该使其支持此接口,该接口提供反序列化功能(如果它有时从Interface Builder或其中使用)。这就是required的原因。

答案 2 :(得分:2)

如果您在 Interface Builder 某处使用此类,而 以编程方式 在其他地方使用此类,并且无论你如何使用类,都必须完成设置工作,这样就更容易编写init()

将按钮放在.nib或storyboard中时会自动调用

init(NSCoder:),编译器确切地知道视图的框架,因此不需要init(CGRect:)。相反,在使用代码创建视图时通常使用init(CGRect:),您希望确保在两个初始化过程中都执行setup(),因此您将setup()放在两个初始化函数中。 / p>