Why convenience keyword is even needed in Swift?
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
The convenience keyword exists so Swift can distinguish between initializers that fully establish an object and initializers that merely delegate to another initializer. That distinction lets the compiler enforce the class-initialization rules cleanly, especially across inheritance and Swift's two-phase initialization model.
Swift has two kinds of class initializers
For classes, Swift separates initializers into:
- designated initializers
- convenience initializers
A designated initializer is responsible for fully initializing the properties introduced by that class and then delegating upward to a superclass initializer if needed.
A convenience initializer is a secondary entry point that must delegate sideways to another initializer in the same class.
That difference is not just style. It affects which initializer is allowed to call what.
The keyword makes delegation rules explicit
Consider this class:
Here, init(width:height:) is the designated initializer because it actually sets stored properties. init(square:) is a convenience initializer because it does not initialize properties directly. It delegates to the real initializer.
The convenience keyword tells the compiler which initializer category this belongs to, so the compiler can apply the right rules.
Why Swift cares so much about this
Swift class initialization follows a strict model often summarized as:
- designated initializers delegate up
- convenience initializers delegate across
That prevents half-initialized objects and ambiguous initialization flows. If Swift allowed every initializer to call any other initializer without classification, the initialization graph would be harder to reason about and the safety guarantees would weaken.
The keyword gives the compiler enough structure to reject invalid chains before runtime.
Inheritance is where the distinction becomes important
The need becomes clearer with inheritance:
Car.init(brand:) is designated because it initializes brand and then calls super.init. Car.init() is convenience because it does not establish the object on its own. It routes through another initializer in the same class.
Without explicit classification, Swift would have a harder time enforcing the required initialization order between subclass state and superclass state.
The keyword supports two-phase initialization
Swift uses two-phase initialization to make sure stored properties are initialized before the object is used. A convenience initializer is not allowed to skip that process. It must eventually end at a designated initializer that performs the real setup.
So convenience is partly a promise:
- "this initializer is not the final authority for object initialization"
That promise helps the compiler keep initialization safe and predictable.
Could Swift have inferred it automatically
In some simple cases, maybe. But explicit syntax avoids ambiguity and keeps class API design clear to readers as well as to the compiler. When you read a class, convenience immediately tells you:
- this is a helper entry point
- it must delegate within the same class
- the real initialization work lives elsewhere
That is valuable documentation embedded in the language.
It is mostly a class concern
This distinction matters for classes because they support inheritance and reference semantics. Structs and enums have simpler initialization rules and do not need the same designated-versus-convenience split.
That is why the keyword feels "extra" at first. It exists to solve class-initialization complexity, not general initialization complexity.
Common Pitfalls
- Thinking
convenienceis just a naming preference rather than a delegation rule. - Trying to do full initialization work inside a convenience initializer.
- Forgetting that convenience initializers must call another initializer in the same class.
- Missing why inheritance makes initializer classification more important.
- Assuming structs should need the same initializer categories as classes.
Summary
- '
conveniencemarks an initializer as a secondary delegating entry point.' - It lets Swift distinguish real object-establishing initializers from helper initializers.
- The keyword supports safe initialization rules, especially with inheritance.
- Convenience initializers must eventually end at a designated initializer.
- The distinction exists because class initialization is complex enough that Swift benefits from making it explicit.
Related reading
- Why create Implicitly Unwrapped Optionals, since that implies you know there''s a value?
- Why do I get iOS linker errors with my static libraries?
- Why do I need 1x, 2x and 3x iOS images?
- Why do I need underscores in swift?
- Why do most fields class members in Android tutorial start with m?
- Why do we use use_frameworks in CocoaPods?
- Why does an image captured using camera intent gets rotated on some devices on Android?
- Why does Apple recommend to use dispatch_once for implementing the singleton pattern under ARC?
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.