When would a class ever have more than one designated initializer? - ios

Reading through Apple's documentation on Tips and Techniques for Framework Developers, I came across this statement about designated initializers:
A designated initializer is an init method of a class that invokes an
init method of the superclass. (Other initializers invoke the init
methods defined by the class.) Every public class should have one or
more designated initializers.
(Emphasis added.)
Based on my understanding—and indeed, the very use of the word "designated"—a class should have only one designated initializer. But according to the documentation, multiple designated initializers are acceptable.
Assuming that you have two (or more) designated initializers, their role is to call the superclass's designated initializer in order to guarantee proper object initialization. But if both designated initializers are calling the same superclass's designated initializer, then why was there the need for more than one in the first place? Shouldn't the class be refactored to funnel all the other init methods to the singular designated initializer?
I'm just a bit confused as to what use case or design pattern would call for multiple designated initializers?

You would do this when you want to have a different initialization for different objects of the same class. One example is class clusters, like NSNumber. It has quite a few initializers for the different types of numbers they can hold. To provide the most accurate representation, the class should hold its value in the same format it received it in, instead of casting. This means the initializers can't simply call a common initializer and return. They need to do some custom work. This makes them a designated initializer.
Another example would be a document class which needs to do some initialization only for new files and some other initialization only for documents being opened. Both of these initializers will call their super implementation, which in turn calls the plain init method to do common initialization. However, since they do more than simply calling another initializer with a default value, they are considered designated initializers.

Related

Can a subclass not inherit the superclass' initializer and when do we use the required initializer?

The required modifier is "to indicate that every subclass of the class must implement that initializer" :
class SomeClass {
required init() {
// initializer implementation goes here
}
}
This entails that the subclasses don't have to inherit the superclasses' initializers. In fact, this Stackoverflow answer says that if a subclass has a designated initializer of its own, then it doesn't have to inherit the superclass' initializer.
However, the Swift documentation says that every class has to have a at least one designated initializer that "calls an appropriate superclass initializer to continue the initialization process up the superclass chain."
My questions are:
Can a subclass not inherit the superclass' initializer and, if so, in what cases it is beneficial to not inherit it?
What exactly does the required initializer do and in what case is satisfying the initializer inheritance requirement necessary?
Try and think about it in terms of what initialization does for an object. It sets values to parameters that do not have values set to them yet that need values set before use. See: https://docs.swift.org/swift-book/LanguageGuide/Initialization.html#ID228. So each class needs to have a way to initialize it and if necessary deal with setting variables or passing that responsibility along the subclass chain. The required init() function should be used as a unique case where somewhere in the initialization chain a special property is computed/set in required init() of a super class that makes it a requirement to call required init() in a subclass/subclasses of it. You do not need to write override required in this case.

In Objective-C, how to decide which initializer is the designated one?

I read some material which says that the designated initializer is the "most complete" initializer in the initializer list.
But for example in UIView initWithFrame:(CGRect)Frame and initWithCoder:(NSCoder*)aDecode both take 1 parameter, how to decide which one's is the UIView's designated initializer?
When you have access to the source, you can recognize the designated initializer as the one that calls super init while all the others just call that one either directly or indirectly - assuming the author follows this convention. They might also use the NS_DESIGNATED_INITIALIZER macro to make this explicit (read more here). When you don't have access to the source code, as is the case with Apple's classes, then they need to tell you somehow - luckily they do so in the class references - e.g. you can see in the reference for UIView that initWithFrame: is the designated initializer.
Command + click the initializer you want to know about. In the documentation it will be mentioned if the initializer is the designated or default initializer.
For UIView default initializer is:
- (instancetype)initWithFrame:(CGRect)frame; // default initializer

Why do we need to override superclasses' designated initializer

In Aaron Hillegass' Objective-C programming book, he gives a few rules on writing custom init methods. One of the rules is that "if the designated initializer of your class is different from the designated initializer of its superclass, you must override the superclass' designated initializer so that it calls the new designated initializer (of your new class)"
Why is this mandated. The only issues I see is that any instance variables in your class will be initialized to null until you explicitly initialize them using their setter. What is the problem with that?
This is because every initializer for a class must go through the designated initializer for the class, that ensures all common setup occurs in one place. Even the superclass' designated initializer should go through your subclass' one, should you make it designated, otherwise setup occurring in your designated initializer could be missed by naïve clients calling into a different initializer.
because it make sure all init for object must call your class designated initializer. If not override designated initializer of its superclass what happen if current class (your custom class) init with one super's initial (designated or convenience) method? your designated initial never called

Calling super.init() in initializer of NSObject subclass in Swift

I'm building an iOS app in Swift and drawing on the Lister sample project Apple provides.
Lister uses two model objects: List and ListItem. I found that both of them do not call super.init() in their initializers even though they subclass NSObject.
However, in the Objective-C version of Lister, both model objects (AAPLList and AAPLListItem) do call [super init].
The Swift Programming Language clearly states that “designated initializers must call a designated initializer from their immediate superclass.” (Rule 1 of Initializer Chaining in Initialization)
What's going on here? Why is this an exception and if you shouldn't always call super.init() in a subclass, what rules do apply?
Even though I can't find a place in the documentation where this is described, what happens is that the default superclass initialiser is called at the end of the subclass initialiser if that is the only initialiser of the superclass, and it wasn't called explicitly.
NSObject only has the default initialiser (init()); you can see that the superclass initialiser is called at the end of the subclass initialiser by attempting to reference self (eg. println(self)) in a constructor that does not call super.init(): You are not allowed to do it because the class is not fully initialised at that point.
If you want to use self somewhere in the constructor, the object needs to be fully constructed at that point, so you need to call super.init() manually before then.

Purpose of init pattern in obj-c and its use

What is the purpose of the initializer pattern other then in order to assure that the object is properly initialized by its superclass before the init method performs its initialisation.
Why is this necessary?
and
when we have a class which has more than one initialization method, why others shoud call the dedicated initialiser instead of superclass initialiser?
I'm coming from java background so don't fully understand this - the closest i could match in java was singleton pattern but the part others calling dedicated initialiser didn't make sense to me as in java you have a choice rather then you "should".
can any one elaborate....thx
The initializer pattern is necessary, because the super class whose initializer you are calling, can return any kind of object, not necessarily the instance of that class. That's how, for example, NSString works, it's actually a cluster of classes implementing different kinds of strings optimized for different usage patterns. So calling self = [super init] for NSString descendant makes self, for example, an NSCFString instance.
There's a pattern called Designated Initializer in Objective C. If the class has many initializer, one of them is chosen as designated, and all the other should be implemented by calling it, not the super. This is important for correctly overriding initializers in child classes, you should initialize only the designated one, and it will be called under all circumstances (assuming your code is well-written and takes advantage of designated initializers, of course :)

Resources