Convenience initializers in Swift - Time & Space Complexity
When using convenience initializers in Swift, it's helpful to know how the time to create an object changes as input grows.
We want to see how the number of steps to initialize an object scales with input size.
Analyze the time complexity of the following code snippet.
class NumberList {
var numbers: [Int]
init(numbers: [Int]) {
self.numbers = numbers
}
convenience init(count: Int) {
var temp = [Int]()
for i in 1...count {
temp.append(i)
}
self.init(numbers: temp)
}
}
This code creates a list of numbers either from an existing array or by building one from 1 to count.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The for-loop that appends numbers from 1 to count.
- How many times: Exactly count times, once for each number.
As the count grows, the loop runs more times, adding one number each time.
| Input Size (count) | Approx. Operations |
|---|---|
| 10 | 10 appends |
| 100 | 100 appends |
| 1000 | 1000 appends |
Pattern observation: The work grows directly with the input size; doubling count doubles the steps.
Time Complexity: O(n)
This means the time to initialize grows linearly with the number of items you want to create.
[X] Wrong: "Convenience initializers always run instantly regardless of input size."
[OK] Correct: Because if the initializer builds or processes data in a loop, the time depends on how much data it handles.
Understanding how initializers scale helps you write efficient code and explain your design choices clearly in interviews.
"What if the convenience initializer used recursion instead of a loop? How would the time complexity change?"
Practice
convenience initializer in Swift?Solution
Step 1: Understand the role of convenience initializers
Convenience initializers are shortcuts to create objects more easily by calling a designated initializer.Step 2: Compare options with this role
Only To provide an easier way to create an object by calling a designated initializer describes this purpose correctly; others describe unrelated concepts.Final Answer:
To provide an easier way to create an object by calling a designated initializer -> Option AQuick Check:
Convenience initializer = shortcut calling designated initializer [OK]
- Thinking convenience initializers create objects independently
- Confusing convenience initializers with deinitializers
- Believing convenience initializers override superclass initializers
Solution
Step 1: Recall the correct syntax for convenience initializers
In Swift, the keywordconveniencecomes beforeinitwithout any function keyword.Step 2: Check each option
convenience init(name: String) { self.init() } matches the correct syntax. Options B, C, and D misuse keywords or order.Final Answer:
convenience init(name: String) { self.init() } -> Option DQuick Check:
Keyword order: convenience before init [OK]
- Placing 'convenience' after 'init'
- Using 'func' keyword with initializers
- Incorrect keyword order causing syntax errors
class Car {
var color: String
init(color: String) {
self.color = color
}
convenience init() {
self.init(color: "Red")
}
}
let myCar = Car()What is the value of
myCar.color?Solution
Step 1: Understand the initializers in the Car class
The designated initializer sets the color property. The convenience initializer calls the designated one with "Red".Step 2: Analyze the object creation
CreatingmyCarwithCar()calls the convenience initializer, which sets color to "Red".Final Answer:
"Red" -> Option BQuick Check:
Convenience init sets color to "Red" [OK]
- Assuming color is empty or nil without initialization
- Thinking convenience init does not call designated init
- Expecting compilation error due to missing default init
class Person {
var name: String
convenience init() {
self.name = "Unknown"
}
init(name: String) {
self.name = name
}
}Solution
Step 1: Recall rules for convenience initializers
A convenience initializer must call another initializer in the same class, not assign properties directly.Step 2: Check the convenience init implementation
Here,self.name = "Unknown"is assigned directly, which is not allowed.Final Answer:
Convenience initializer must call a designated initializer, not assign properties directly -> Option AQuick Check:
Convenience init must call designated init [OK]
- Assigning properties directly in convenience initializer
- Marking designated initializer as convenience
- Making properties optional unnecessarily
Rectangle with a designated initializer that takes width and height, and a convenience initializer that creates a square by taking only one side length. Which of the following implementations correctly uses a convenience initializer?Solution
Step 1: Identify designated and convenience initializers
The designated initializer takes width and height. The convenience initializer should call the designated one.Step 2: Check each option for correct usage
class Rectangle { var width: Double var height: Double init(width: Double, height: Double) { self.width = width self.height = height } convenience init(side: Double) { self.init(width: side, height: side) } } correctly defines the designated init and the convenience init calls it with equal sides. Others either misuse convenience keyword or assign properties directly.Final Answer:
class Rectangle { var width: Double var height: Double init(width: Double, height: Double) { self.width = width self.height = height } convenience init(side: Double) { self.init(width: side, height: side) } } -> Option CQuick Check:
Convenience init calls designated init with side values [OK]
- Marking designated initializer as convenience
- Assigning properties directly in convenience initializer
- Not calling designated initializer from convenience initializer
Ready to prove it?
Pass the test and this pattern moves unknown
