Is it necessary to implement all initializers for NSTextFieldCell subclass? - objective-c

As per the docs, I have created a custom subclass of NSTextFieldCell with the sole purpose of overriding the method setUpFieldEditorAttributes:.
The docs don't mention any initializers for NSTextFieldCell's or its super class NSActionCell, but the documentation for NSCell explicitly mentions:
When subclassing NSCell you must implement all of the designated
initializers. Those methods are: init, initWithCoder:, initTextCell:,
and initImageCell:.
Now, since I don't really do anything in the custom subclass, except override an explicit override point in the Cocoa class, is there really any point in creating 4(!) initializers which only call their super class implementations?
Due to the verbose nature of the init... methods in Objective-C, this would quintuple the lines of code in the implementation, the number of comments to write (and read, for people into that sort of thing) and generally maintain.
I know that I could just have created those methods in the time it took me to write this, but I genuinely wonder if the existence of a method that just calls super makes any difference?
Edited to add:
I misread the NSTextFieldCell docs, which also state that all of the designated initializers must be implemented, but the question still stands - do 3 (init somehow disappeared as a designated initializer down the inheritance chain) initializers that just call super really make any difference?

In Apple's "DragNDropOutlineView" sample code, they implement "ImageAndTextCell", a custom subclass of NSTextFieldCell.
In it, the only initializer they override is
-(id) init
NSTextFieldCell apparently handles the others for you.
And, as you state, overriding a superclass's methods simply to call the superclass is a waste of time, as the runtime will do that if you don't override it anyway.

Related

Must you override init when you create a new designated initializer?

I have read up quite a bit on designated and convenience initializers in objective-c and feel I have a good understanding of how and why they are used. I just have a couple of outstanding questions, well one really.
Say you have a class that inherits directly from NSObject and you create a designated initializer for it.
I realise you can now mark your designated initializer using NS_DESIGNATED_INITIALIZER but I am wondering if that means it forces you to separately, within the same class, first override init with a call to your designated initializers?
Secondly, if you weren't to use this macro, what might the implications be of NOT overriding init explicitly with the call to the designated initializer? I realise the compiler would not know which was the designated initializer, so could anything bad come of this, and is it just good practice to also override init when you create a new designated initalizer for your class?
EDIT: I just want to add further clarification on this question. I have seen examples of good coders not adding a distinct method to override init despite having added a designated initialiser of their own making.
When I ask if you should override init I mean in addition to creating your own specific designated initialiser which of course should call its superclass's init method. I have seen a good coder not do this and so I wondered why you would therefore do it.
you can now mark your designated initializer using NS_DESIGNATED_INITIALIZER but I am wondering if that means it forces you to separately, within the same class, first override init with a call to your designated initializer?
Calling any initializer in self will bypass the warning. When I try to call a super.init method I do get the following warning.
Convenience initializer missing a 'self' call to another initializer.
what might the implications be of NOT overriding init explicitly with the call to the designated initializer?
This would mean your object might be missing some important information that it requires to function, or that the app assumes the object always has, and if it doesn't have it, it could cause errors or a crash in your app.
Here is a good explanation of how it works:
http://timekl.com/blog/2014/12/09/objective-cs-designated-secret/

How to mark designated initializers of super class "invalid" in Objective-C?

From the Adapting Modern Objective-C document:
If a class provides one or more designated initializers, it must implement all of the designated initializers of its superclass.
That means if I have a subclass of NSObject that has its own designated initializer, say
- (instancetype)initWithImage:(UIImage*)image NS_DESIGNATED_INITALIZER;
then I also need to provide an implementation of NSObjects -init. What should I do to mark the -init initializer as "invalid", i.e., nobody should call it but use -initWithImage: instead? What's best practice here?
Edit
I tried the techniques described here.
However, when I mark the superclass -init method as unavailable in the interface, the compiler still tells me that I need to overwrite the initializer of the superclass.
When I try the other techniques, i.e., raising an exception or calling -doesNotRecognizeSelector: inside of -init, I get an error stating that I need to call one of my designated initializers.

Must an Objective-C class have exactly one designated initializer?

I found some info of the designated initializer in this Apple's docs, but what I don't understand is, must each class have one and only one designated initializer?
For example, what if class A has initL, initM, initN, while class B inherits from class A and has initX, initY, initZ. Is there a rule that says we can't have initX call [super initL], and initY call [super initM], and initZ call [super initN]?
That is, instead of all "secondary initializers" call the designated initializer, and then each designated initializer will call the [super initFoo] where initFoo is the superclass's designated initializer, can't we just have 3 primary initializers, and each one caller its corresponding superclass's 3 primary initializers? (and say, these all inherit from NSObject and just call self = [super init].)
No, an obj-c class may have multiple designated initializers. The most common example of this is -initWithCoder: vs -init. The former is used when unarchiving an object, and the latter is used for all other initialization.
That said, it's generally good practice to only have one designated initializer outside of -initWithCoder:. This helps to prevent code duplication and makes it obvious which method a subclass has to override if they want to be invoked for all initializations. But if you have a good case for needing 3 distinct designated initializers, then there's nothing stopping you from doing it. Just be sure to document it properly.
Designated initializers are a concept that helps to prevent recursive calls and omitted important base class initialization. It is possible to not follow the designated initializer rules and still build a working class hierarchy.
In fact there are patterns in Cocoa that deviate from pure designated initializes: NSCoding for example requires to initialze objects using initWithCoder: but you can still initialize objects from code using the other initializers.

Methods required to be implemented when subclassing in Objective C

I am new at programming in general (though I have had a C class many, many years ago) and am learning Objective-C for programming on the iPhone. I have what I think is a simple question, but after looking for a while (days, off and on) I can't find the answer that I'm looking for explicitly.
I know that when subclassing an Objective-C class I should implement the initialize method along with the deallocate method (unless using ARC for the latter, if I am correct?). The questions are:
Are these the only two to worry about, or will other classes potentially have additional methods that can be required to be implemented?
If other classes might have methods that I am required to implement when subclassing them, where is that documentation typically found? (I don't seem to see that in the Apple framework docs, though that kind of information is there for protocols it appears)
Thanks for your help!
Technically, you are not required to implement even the init and dealloc if the inherited versions are sufficient. Also, ARC does not free you from having to write dealloc in all cases (but it certainly covers the overwhelming majority). For example, if you allocate memory for your object using malloc, you need to free it in the dealloc.
When you add instance variables to your class, you need to initialize them. Typically, you do that in a designated initializer. Again, if you do not to initialize anything, you do not have to code your own initializer; same goes for deinitializer.
The only case when you need to implement a method is when you adopt a protocol with one or more methods marked #requried. These methods are marked in the protocol reference. For example, tableView:cellForRowAtIndexPath: and tableView:numberOfRowsInSection: are marked with the "required method" tag in Apple's documentation.
No methods are required when subclassing an NSObject (or any of their subclasses, such as UIViewController, UIView, etc. etc.).
If you create a new, let's say UIViewController, it's generally a good idea to keep the methods you find in the newly created file as a guideline/template, but you're not really required to keep any of the methods. The super class will always call the methods on itself.
Be aware, though, some methods you have to call super, like viewWillAppear, etc.

Objective C subclass that overrides a method in the superclass

In Objective C, if you are subclassing something, and are planning to override a method on the superclass, should you re-declare the superclass method in your subclass #interface?
For example, if you are subclassing UIViewController (e.g. MyViewController), and you are planning to override "viewDidLoad" should you include that method in your MyViewController #interface declaration, or just implement it in MyViewController.m?
In examples I've come across, I've seen it done both ways (re-declaring the method in your subclass interface, or not re-declaring the method). There may not be any functional difference, but what is the best practice?
I often declare methods that I plan to override in either the public header or at least in a private category. The benefit to this is that you'll get an incomplete class definition warning if you forget to actually override the method... which comes in handy from time to time.
As for when to place it in the public header, that's pretty subjective and probably up to you/your team's coding styles. I usually only redeclare a method in the public header if I plan to radically change what the method is going to do or if I plan not to invoke the super class's version of the method.
People often use the header as documentation for the class (and tools like AutoDoc support this). Obviously, if you're following that convention, the only sensible choice is to include redefined methods so you can explain what you've done with them. Otherwise your docs for the class are either incomplete or scattered to the four corners of the earth.
But if we're just copy-pasting the declaration, I don't personally like to redeclare methods. It's not DRY and it bloats your header unnecessarily. Less code is better code.