Designated initializers tend to set all of the properties up and let the user send in values for each. A convenience initializer often has some of those hard coded, and thus can take less parameters
To simplify the relationships between designated and convenience initializers, Swift applies the following three rules for delegation calls between initializers:
Rule 1
A designated initializer must call a designated initializer from its immediate superclass.
Rule 2
A convenience initializer must call another initializer from the same class.
Rule 3
A convenience initializer must ultimately call a designated initializer.
A simple way to remember this is:
Designated initializers must always delegate up.
Convenience initializers must always delegate across.
下面舉例說明以上幾點:
首先我們創建一個子類繼承UIView, 添加自己的一個init方法(Designated initializers):
init(frame: CGRect, bgColor: UIColor, tag: Int, superView: UIView) {
}
在這裏, 我們需要遵循Rule 1,調用父類的Designated initializers
init(frame: CGRect, bgColor: UIColor, tag: Int, superView: UIView) {
super.init(frame:frame) // not super.init()
self.backgroundColor = bgColor
self.tag = tag
superView.addSubview(self)
}
接下來,我們再創建兩個Convenience initializers
convenience init(bgColor:UIColor) {
self.init(frame:CGRectZero,bgColor:bgColor)//Rule 2
}
convenience init(frame: CGRect,bgColor:UIColor) {
self.init(frame: frame, bgColor:bgColor, tag: 0)//Rule 3
}
使用Designated Initializer的好處:
在修改代碼之前,應該想清楚是否需要刪除原有代碼。類似這種擴展,舊的接口可以留下來,然後在其中調用多參數的Designated Initializer。保證良好的編寫Designated Initializer的風格,可以讓我們節約很多時間,避免潛藏的bug出現