Initialization means to set to the value, or put in the condition, appropriate to the start of an operation.
In Swift, “Initialization is the process of preparing an instance of a class, structure, or enumeration for use. This process involves setting an initial value for each stored property on that instance and performing any other setup or initialization that is required before the new instance is ready for use.
You implement this initialization process by defining initializers, which are like special methods that can be called to create a new instance of a particular type. Unlike Objective-C initializers, Swift initializers do not return a value. Their primary role is to ensure that new instances of a type are correctly initialized before they are used for the first time.
A basic initializer in Swift looks like:
1 2 3 |
init() { // perform some initialization here } |
Instances of class types can also implement a deinitializer, which performs any custom cleanup just before an instance of that class is deallocated” (Ref: A).
Designated Initializers
Image Source Ref#: J (originally from Apple Docs)
- Designated initializers are the primary initializers for a class
- They have to fully initialize all the properties introduced by that class
- They must also call a designated initializer from their immediate superclass (then up the chain of classes)
- Classes will typically have one designated initializer, but can easily have more
- Every class must have at least one designated initializer.
- The chain of delegating initializers will end by a call to a non-delegating initializer
In some cases, this requirement is satisfied by inheriting one or more designated initializers from a superclass because of Automatic Initializer Inheritance.
Designated initializers for classes are written in the same way as simple initializers for value types.
Syntax
So these are the inits
we all used to seeing in our Swift code, such as:
1 2 3 4 5 |
init(sender: String, recipient: String) { self.sender = sender self.recipient = recipient super.init() } |
OR
1 2 3 4 5 6 7 |
init(delegate: ABCLocationManagerDelegate?) { // A designated initializer must call a designated initializer // from its immediate superclass: super.init() self.delegate = delegate self.configureLocationManager() } |
Or if with our ViewControllers
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// MARK:- Custom initializers for our view controller to allow for // dependency injection of our services init(networking: OURNetworking, menu: SubLevelMenu) { self.networking = networking self.subMenu = menu super.init(nibName: nil, bundle: nil) self.doSomethingWithOurProductAndMenuInfo() } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } |
Convenience Initializers
- secondary, supporting initializers for a class
- they’ve got to call a designated init from the same class
- you don’t need these but they can help to widen your options
- You can define a convenience initializer to create an instance of your class for a particular use-case or input value type.
- place the
convenience
word before init to make one of these. - these can be shortcuts to common initialization patterns
Syntax
1 2 3 |
convenience init(parameters) { statements } |
Basic Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
class Television { var make : String var sizeInInches : Int // This is the designated initializer of the class Television init(make : String, diameter: Int) { self.make = make self.sizeInInches = diameter } // This is a convenience init allowing us to generate a Television without giving it any params convenience init() { self.init(make: "LG", diameter: 27) } } var tv = Television() print(tv.make) // LG print("\(tv.sizeInInches)\"") // 27" |
Real-World Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// If we extend UIColor, we could add a convenience initializer // therefore allowing us to generate a Color with a hex string convenience init(hexString: String) { let hex = hexString.trimmingCharacters(in: CharacterSet.alphanumerics.inverted) var int = UInt32() Scanner(string: hex).scanHexInt32(&int) let alpha, red, green, blue: UInt32 switch hex.count { case 3: // RGB (12-bit) (alpha, red, green, blue) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17) case 6: // RGB (24-bit) (alpha, red, green, blue) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF) case 8: // ARGB (32-bit) (alpha, red, green, blue) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF) default: (alpha, red, green, blue) = (255, 0, 0, 0) } //So here is where we call a Designated Initializer of UIColor (having converted into a format it can understand) self.init(red: CGFloat(red) / 255, green: CGFloat(green) / 255, blue: CGFloat(blue) / 255, alpha: CGFloat(alpha) / 255) } |
This from the Apple Docs is another good demonstration:
To recap then:
- A Designated Initializer must call a Designated Initializer from its immediate superclass.
- A Convenience Initializer must call another initializer from the same class.
- A Convenience Initializer has to ultimately call a designated initializer.
Automatic Initializer Inheritance
Subclasses do not inherit their superclass initializers by in all cases, but superclass initializers are automatically inherited if certain conditions are met.
“””
If we 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.
“””(Ref #: K).
MORE INFORMATION ON INITIALIZERS
Throwable Initializers
Using Error Handling we are able to make a Struct(or a class) initializer into a so-called throwable initializer.
Example Error Handling enum:
1 2 3 |
enum ValidationError: Error { case invalid } |
You can use Error Handling enum to check the parameter for the Struct(or class) meet expected requirement
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
struct Student { // The matriculation number is actually a string let matriculationNumber: String init(name: String?) throws { guard let name = name else { ValidationError.invalid } self.name = name } } // Now, you can use the throwable initializer using the do-try-catch syntax // like this: do { let student = try Student(matriculationNumber: "04911506") // success } catch ValidationError.invalid { // handle error } |
Source: Swift Notes for Professionals
Required Initializers
Writing the keyword required
before the initializer tells us that each subclass must implement that initializer. Furthermore, using this means required
modifier must be present at the respective subclass implementations as well.
This is exactly why we need this bit of code when were using initializer dependency injection as in the above example:
1 2 3 |
required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } |
For a more comprehensive breakdown, an ok reference is found here: https://docs.swift.org/swift-book/LanguageGuide/Initialization.html
Some Syntactic Sugar
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
import UIKit enum Gender { case male case female } class Human { var age: Int? var gender: Gender? // We can pop in some underscrores like this to negate the need to // name the parameters upon initialization. init(_ age: Int,_ gender: Gender) { self.age = age self.gender = gender } } // Thus we can have (from the context of initialization) let dave = Human(40, .male) let clara = Human(22, .female) |
Further Illustration (Source: Apple Docs)
References
A: https://docs.swift.org/swift-book/LanguageGuide/Initialization.html
B: https://useyourloaf.com/blog/adding-swift-convenience-initializers/
C: https://www.raywenderlich.com/1220-swift-tutorial-initialization-in-depth-part-1-2
D: https://www.raywenderlich.com/1219-swift-tutorial-initialization-in-depth-part-2-2
E: https://www.tutorialspoint.com/swift/swift_initialization
F: https://www.journaldev.com/16889/swift-init
G: https://docstore.mik.ua/orelly/java-ent/jnut/ch03_02.htm
H: https://www.programiz.com/kotlin-programming/constructors
I: https://www.tutorialsteacher.com/csharp/csharp-object-initializer
J: Swift Notes for Professionals
2,216 total views, 2 views today
Comments