Swift has a feature, originally from Objective-C, where initializers are inherited from the base class. Swift is a little stricter about this than Objective-C, being a language without implicit nullability, so by default it will only do this if you give all your properties initial values (or make them optional), and don’t provide any explicit initializers of your own.
What’s different about Swift from other languages with initializer inheritance is that it also allows a subset of initializers to be automatically inherited even if you implement your own. For this to be safe even for arbitrary subclasses, the inherited initializers must defer to another initializer to initialize all the class’s properties—even if it’s a subclass. But because the subclass can’t see the body of a superclass’s initializer, it can’t know whether it’s a designated initializer that the others call, or a convenience initializer that ends up calling one of the designated ones.* So we mark the convenience ones specially: the ones that can be inherited if you provide the other initializers yourself. (Note: marking the class final
removes this requirement.)
This feature can mostly be replicated with factory methods and required
initializers, and indeed the places where this feature is most useful in Objective-C that probably would have been fine. But in Objective-C, initializers are just a kind of method, which means they’re always inherited by default, and so the idea was that every initializer was “required” all time, and the convenience init methods were a way to deal with that and also make factory methods look the same as direct initialization idioms.
Swift ended up with the complexity of formalizing what was largely unchecked-but-worked in Objective-C, because of Swift’s stricter type system and deciding to not inherit initializers by default.** I think if Swift hadn’t had ObjC integration as a top goal, it would have left required
inits and factory methods as the way to do this kind of thing.
* The name “designated initializer” makes the most sense when there is one initializer that everything else ends up calling, but sometimes it makes sense to have more than one.
** I wrote about the rules around convenience inits, and some of their problems, in a doc that predates the forums: swift/InitializerProblems.rst at b0c2dbe910564d2e3f97cfeefc71816b6fa0740a · apple/swift · GitHub