我有时会看到这样的视图,在两个不同的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
}
}
答案 0 :(得分:10)
override init(frame: CGRect)
。
required init?(coder: NSCoder)
。
因为后者是必需的,你必须实现它的身体。但是,如果您不打算手动创建按钮,则不需要第一个按钮,可以省略
在两者中调用安装程序,因为无论您选择创建按钮,都要设置其自定义行为,以便按预期方式工作
答案 1 :(得分:4)
当override
初始值设定项(例如init(frame: CGRect)
)时,您可以针对指定的初始值设定项执行此操作,即负责以编程方式创建对象的主体初始值设定项。根据规则,您必须在执行任何其他初始化操作之前致电super.init
。
另一方面,所需的初始化程序与指定的不同。
必需的初始化程序
在定义类之前编写必需的修饰符 初始化程序,表示该类的每个子类都必须 实现初始化程序。
您还必须在每个子类之前编写必需的修饰符 执行一个必需的初始化程序,以表示该 初始化程序要求适用于链中的其他子类。 覆盖必需时,不要写覆盖修饰符 指定的初始化程序。
如果原始类具有标记为必需的初始化程序,则在创建子类时,无论您的意愿如何,都可以实现所需的初始化程序。通常,您不应该直接调用它来创建对象,尽管在某些情况下您可以这样做。标记为必需的初始化程序,以符合若干要求。例如,
在几种情况下调用required init?(coder: NSCoder)
。一种情况:视图是从IB创建的。另一种情况 - 手动创建对象时,或者更确切地说,取消归档(称为反序列化)。实际上,当您将该对象放在ViewController的视图上时(例如),该对象也 unarchived ,即加载并设置其所有属性。
显然,当您创建某个视图的子类时,您应该使其支持此接口,该接口提供反序列化功能(如果它有时从Interface Builder或其中使用)。这就是required
的原因。
答案 2 :(得分:2)
如果您在 Interface Builder 某处使用此类,而 以编程方式 在其他地方使用此类,并且无论你如何使用类,都必须完成设置工作,这样就更容易编写init()
。
init(NSCoder:)
,编译器确切地知道视图的框架,因此不需要init(CGRect:)
。相反,在使用代码创建视图时通常使用init(CGRect:)
,您希望确保在两个初始化过程中都执行setup()
,因此您将setup()
放在两个初始化函数中。 / p>