Notes on Initialization in Swift
Some links on initializers in Swift:
- Objective-C’s Designated Secret - don’t panic: A discussion of LLVM designated initializers in Objective-C and Swift, including common pitfalls, how to use designated vs. convenience initializers, and what methods you need to override when subclassing.
- Xcode 6.0 Beta 5 change: Required and designated initializers in subclasses. “Swift compiler now strictly enforces the presence of required initializers in subclasses. If an ancestor of a class conforms to a protocol requiring a specific initializer and the class doesn’t inherit that initializer automatically, it must define it by itself. … What it means, most commonly, is that if you subclass a Cocoa class that conforms to
NSCoding
(e.g.UIView
) and add your own designated initializer, you must also defineinit(coder:)
.” - Notes on Modifying constant properties in designated vs. convenience initializers, from Chris Lattner. “… initializers have privledged access to ‘let’ properties while they run: these properties are actually mutable when accessed directly within the initializer. This is very useful when you’re configurating an object during its setup, but it is absolutely required when you have an immutable property dependent on some argument to the initializer …”
And some relevant, practical excerpts from Apple’s Swift book:
Unlike subclasses in Objective-C, Swift subclasses do not inherit their superclass initializers by default. Swift’s approach prevents a situation in which a simple initializer from a superclass is inherited by a more specialized subclass and is used to create a new instance of the subclass that is not fully or correctly initialized.
Assuming that you provide default values for any new properties you introduce in a subclass, the following two rules apply:
Rule 1 If your subclass doesn’t define any designated initializers, it automatically inherits all of its superclass designated initializers.
Rule 2 If your subclass provides an implementation of all of its superclass designated initializers—either by inheriting them as per rule 1, or by providing a custom implementation as part of its definition—then it automatically inherits all of the superclass convenience initializers.
These rules apply even if your subclass adds further convenience initializers.
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.