- Definition
- Relationships between designated and convenience initializers
- Sample code – Designated、Convenience initializers
Definition:
Designated initializers:
Designated initializers are the primary initializers for a class. A designated initializer fully initializes all properties introduced by that class and calls an appropriate superclass initializer to continue the initialization process up the superclass chain.
Convenience initializers:
Convenience initializers are secondary, supporting initializers for a class. You can define a convenience initializer to call a designated initializer from the same class as the convenience initializer with some of the designated initializer’s parameters set to default values.
Failable Initializers:
To cope with initialization conditions that can fail, define one or more failable initializers as part of a class, structure, or enumeration definition. You write a failable initializer by placing a question mark after the init keyword (init?).
A failable initializer creates an optional value of the type it initializes. You write return nil within a failable initializer to indicate a point at which initialization failure can be triggered.
EX:
class Test4 {
var input: String
init?(input: String) {
guard !input.isEmpty else {
return nil
}
self.input = input
}
}
if let t4 = Test4(input: "") {
print("t4.input: \(t4.input)")
} else {
print("initialization fail")
}
Relationships between designated and convenience 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.
Note:
A simple way to remember this is:
– Designated initializers must always delegate up.
– Convenience initializers must always delegate across.

Sample code – Designated、Convenience initializers:
class Test2 {
var input: Int
var input2: String
init(input: Int, input2: String) {
print("test2 init - designated")
self.input = input
self.input2 = input2
}
convenience init(input: Int) {
print("test2 init - convenience")
self.init(input: input, input2: "test")
}
}
class Test3: Test2 {
override init(input: Int, input2: String) {
print("test3 init - designated")
super.init(input: input, input2: input2)
self.input = input / 2
self.input2 = input2 + "t"
}
convenience init(input2: String) {
print("test3 init - convenience")
self.init(input: 1, input2: input2)
}
}
let t2 = Test2(input: 3)
// Console output:
// test2 init - convenience
// test2 init - designated
let t3A = Test3(input: 1, input2: "a")
// Console output:
// test3 init - designated
// test2 init - designated
let t3B = Test3(input2: "Check")
// Console output:
// test3 init - convenience
// test3 init - designated
// test2 init - designated
Ref: https://docs.swift.org/swift-book/LanguageGuide/Initialization.html