Swift Initializers in Depth
An initializer sets up a new object before it is used. A class can add helper initializers that delegate to the main one, and an initializer can fail and give back no object.
A convenience initializer delegates
The Cup class has a designated initializer that takes a name and a size. The convenience initializer supplies a size of 12 and delegates with self.init.
class Cup {
var name: String
var size: Int
init(name: String, size: Int) {
self.name = name
self.size = size
}
convenience init(name: String) {
self.init(name: name, size: 12)
}
}
let big = Cup(name: "Mug", size: 20)
let plain = Cup(name: "Cup")
print(big.name)
print(big.size)
print(plain.name)
print(plain.size)A failable initializer returns nil
The Bottle initializer fails when the size is not positive. The first call succeeds, and the second call takes the else branch.
class Bottle {
var size: Int
init?(size: Int) {
if size <= 0 {
return nil
}
self.size = size
}
}
if let bottle = Bottle(size: 500) {
print(bottle.size)
} else {
print("No bottle")
}
if let empty = Bottle(size: 0) {
print(empty.size)
} else {
print("No bottle")
}A subclass convenience initializer
LabeledBottle adds a label property and its own designated initializer. Its convenience initializer supplies a size of 500 and delegates to that designated initializer.
class Bottle {
var size: Int
init(size: Int) {
self.size = size
}
}
class LabeledBottle: Bottle {
var label: String
init(label: String, size: Int) {
self.label = label
super.init(size: size)
}
convenience init(label: String) {
self.init(label: label, size: 500)
}
}
let bottle = LabeledBottle(label: "Water")
print(bottle.label)
print(bottle.size)Example
class Reading {
var value: Int
init?(value: Int) {
if value < -273 {
return nil
}
self.value = value
}
}
if let reading = Reading(value: -300) {
print(reading.value)
} else {
print("Too cold to exist")
}
if let ok = Reading(value: 20) {
print(ok.value)
} else {
print("Too cold to exist")
}Key points
- A designated initializer gives a value to every stored property of its class.
- A convenience initializer is a helper marked with the word convenience.
- A convenience initializer delegates with self.init instead of setting properties itself.
- A failable initializer is written as init? and can return nil.
- Returning nil from a failable initializer means no object was made.
- Code that calls a failable initializer tests the result before using it.
In this example, the Reading class has a failable initializer that returns nil for a value below -273. The value -300 takes the else branch and prints the failure line. The value 20 succeeds, so the second check prints 20.
Note
Every convenience initializer chain ends at a designated initializer.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
A bottle is made with Bottle(size: 0), and its failable initializer returns nil for a size that is not positive. What does the caller receive?