Is NSObject init always called? - objective-c

In Cocoa, it's recommended to always called the superclass's designated initializer. Is it safe to assume that init will always be called, during an object's initialization, even if the object isn't initialized with init?
For example, if let's say there's a class: NSThingie, which can be initialized like [[NSThingie alloc] initWithFoo: foo], or [[NSThingie alloc] initWithFoo: foo andBar: bar]. If I override init, can I assume that it will be called at some point during initialization?
EDIT
Maybe my original question wasn't worded so well. I know that overriding init causes init in superclasses to not be called, and I must explicitly call init. What I'm wondering is whether, in the apple frameworks, [NSObject init] is always called. If I initialize some Apple object like [[NSAppleClass alloc] initWithSomething: something], can I assume that NSObject's init will eventually be called during the initialization of NSAppleClass?

short answer: no
you need to make sure you are overriding the correct init method for the class you are using
for example UIView has an init method initWithFrame: and a very basic implementation of that would be:
- (id)initWithFrame:(CGRect)frame
{
self = [super init]; //calls init because UIResponder has no custom init methods
if (self){
self.frame = frame;
}
return self;
}
init is called on the superclass, but not on UIView, so if you were to override init and not initWithFrame: your initialisation code would never be run

If I override init, can I assume that it will be called at some point
during initialization?
If you override and init method you are responsible for calling the designated initializer. It is the responsibility of the developer to call correct initializer of the class that is subclassing. The reason you call the designated initializer is to make sure the class is constructed in its intended state. Not calling the correct initializer or not calling an initializer at all will likely result in undefined/undesirable behavior.

yes the "init" default constructor don't do a spécifique processing
because the init method defined in the NSObject class does no initialization; it simply returns self.

Related

Is not calling [super init] in the init method ever correct?

In Microsoft's WinObjC UIApplication.mm file (at https://github.com/Microsoft/WinObjC/blob/master/Frameworks/UIKit/UIApplication.mm) the init method is implemented for both UIApplication and WOCDisplayMode.
Neither class' init method calls [super init], or any method from that family of methods that would eventually result in a call to [super init]. I've never seen this before, apart from the initialization of NSProxy objects.
I've reproduced the implementation as of this writing of WOCDisplayMode below for reference.
-(instancetype) init
{
_fixedWidth = 320.0f;
_fixedHeight = 480.0f;
_fixedAspectRatio = 0.0f;
_magnification = 1.0f;
_autoMagnification = TRUE;
_sizeUIWindowToFit = TRUE;
_operationMode = WOCOperationModePhone;
return self;
}
It seems to me that this could create a number of problems; for example, if one of the superclasses of UIApplication, like UIResponder, at some point overrode init itself, and set up internal state that future method calls depended on.
Why might the implementor have elected not to call [super init]? Is this ever a justifiable decision? Is it ever the correct one?
This definitely seems like an error on behalf of the author(s) of those classes.
NSProxy does not call [super init] because it is an abstract superclass and does not inherit from NSObject.
Since their implementation of UIApplication inherits from UIResponder, and WOCDisplayMode inherits from NSObject they should be calling [super init] in these classes.
According to the documentation on Object Initialization:
The requirement to invoke the superclass’s initializer as the first
action is important. Recall that an object encapsulates not only the
instance variables defined by its class but the instance variables
defined by all of its ancestor classes. By invoking the initializer of
super first, you help to ensure that the instance variables defined by
classes up the inheritance chain are initialized first. The immediate
superclass, in its initializer, invokes the initializer of its
superclass, which invokes the main init... method of its superclass,
and so on (see Figure 6-1). The proper order of initialization is
critical because the later initializations of subclasses may depend on
superclass-defined instance variables being initialized to reasonable
values.
I would recommend logging it as an issue on the project.

Beginner Objective-C: Extending a class?

I'm very new with objective-C, and I am trying to implement a 'factory' style class extending a cocos2D class called CCSprite.
I want there to be a class Monster which extends CCSprite that will create and issue sprites with unique IDs so that I may call and manipulate the generated sprites later on; I am extending CCSprite to add an instance_id property and a static global_id variable.
I want to be able to use all the CCSprite constructors such as spriteWithImageNamed along with all the other functions CCSprite has, the problem is that my instance_id isn't being assigned/incremented properly(It's always 0), and I don't really know where to start to fix this.
Here is what I have:
Monster.h:
#import "CCSprite.h"
#interface Monster : CCSprite
#property (nonatomic, readonly) int instance_id;
#end
Monster.m:
#import "Monster.h"
static int global_id = 0;
#implementation Monster:CCSprite
#synthesize instance_id;
-(id) init{
self = [super init];
if(self){
instance_id = global_id;
global_id++;
}
return self;
}
#end
Is the init function called every time any constructor is called? (eg spriteWithImageNamed)?
How do I ensure my extended properties and variables are applied when I call the parent class's functions?
In Objective-C, a class's designated initializer is the one that other initializers are supposed to call into. For many classes, this is indeed init. According to the Cocos2D documentation, however, init is not the designated initializer for CCSprite. Instead, the designated initializer is:
- (id)initWithTexture:(CCTexture *)texture rect:(CGRect)rect rotated:(BOOL)rotated
So that is the method you need to override if you want all the other initializers to call your version.
(If you want to confirm for yourself that this works, you can put a log statement or breakpoint in your implementation of the designated initializer, then call other initializers and make sure the designated initializer is called.)
Your init method may or not be called depending on what init these factory methods are using internally. For example, initWithFile may call self = [super init] instead of self = [self init], in which case your implementation will not be called. You can ensure that your initialization is always performed by overriding all init methods of all superclasses and do your necessary setup. Also keep in mind that you can also override any of the factory methods, where you can get the object from calling super, and then assign it's id property before returning.
looking at CCSprite it seems that every factory method like +(id)spriteWith* calls an initWith* method
and every initWith* method at the end of the chain calls [self init]
so if you override the init method as you do in monster.m you are ok!
by the way, if you want to create your sprite using a factory method do not call [CCSprite spriteWith*], call [Monster spriteWith*] instead
best regards

Why to use [super init] in Objective C constructors?

Say I have a class named Item. Which is a superclass of NewsItem and TwitterItem.
If I want to create some NewsItem's do I have to use (inside constructor)
self = [super init];
If yes, why? In Java/C# I would just do,
NewsItem n = new NewsItem();
I don't have to do anything with superclasses in Java/C#. Just can't grasp it.
In Java and C#, the compiler automatically makes your constructor call the superclass constructor if you don't explicitly call it. For example, the “Java Tutorials” say this:
If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the no-argument constructor of the superclass. If the super class does not have a no-argument constructor, you will get a compile-time error. Object does have such a constructor, so if Object is the only superclass, there is no problem.
In Objective-C, the compiler doesn't do it automatically, so you have to do it yourself.
Because your superclass (and your superclass's superclass) need a chance to initialize, too.
And, keep in mind, that your superclass will [rarely] return nil or a different instance.
Which is why you do:
- (id)init
{
self = [super init];
if (self) {
... init stuff ....
}
return self;
}
Because you are overriding the init message. If you don't override it then [[NewsItem alloc] init] would just call the superclass' init message. In C#, you might use base to do the same.
since your custom object will at least inherit from the mothers of all Objects: NSObject, you have to call '[super init];'
'super' simply does call the init Method of its superclass

Should subclasses call the designated initializer in the immediate super class?

I've seen some sample code which has got me wondering about calling the designated initializer in the super classes. Say I have some code this:
#interface NewTableViewCell : UITableViewCell {
}
#end
#implementation NewTableViewCell
- (id) initWithFrame: (CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Do some stuff
}
return self;
}
#end
Note that initWithFrame is the designated initializer for UIView, not UITableView. Should this code always be calling [UITableViewCell initWithStyle:reuseIdentifier:], or does it depend on the coder's intent?
When subclassing, the guideline is that the designated initializer has to call its super class' designated initializer.
Another guideline is that the subclass needs to override the superclass' designated initializer to call the new designated initializer.
If UITableViewCell follows this guideline (and it does; I tested with the help of a category), it overrides its superclass' designated initializer (UIView's initWithFrame:) to call the new designated initializer (initWithStyle:reuseIdentifier:). Therefore, if you call initWithFrame: on UITableViewCell it will call initWithStyle:reuseIdentifier:, which in turn will call initWithFrame: on super (UIView).
Therefore, it will need an additional method call but it will eventually go through initWithStyle:reuseIdentifier:.
Again, the best practice is that the designated initializer has to call the super class' designated initializer and any other initializer that isn't the designated initializer has to call the designated initializer. From "The Designated Initializer":
General principle: The designated initializer in a class must, through a message to super, invoke the designated initializer in a superclass.
Designated initializers are chained to each other through messages to super, while other initialization methods are chained to designated initializers through messages to self.
I agree it depends on the coders attempt but the coder should always try and use the designated initializer. Think about initializers you may have written, they probably do additional work for your object to be in a usable or desired state. If you are overriding an initializer like you are doing in your example you should call the overridden initializer as well. If that was a custom init method then you would want to call the designated initializer because for UITableViewCell's that is the only way to set the reuseIdentifier publicly.
//Override initWithFrame
//Fine although it may not (should not) get called for a UITableViewCell
- (id) initWithFrame: (CGRect)frame {
self = [super initWithFrame:frame];
//Design a custom initializer to gather parameters for supers default initializer
-(id)initWithCustomObject:(id)object style:(UI..Style)style reuseIdentifier:(NSString*)rid {
//This should call initWithStyle:reuseIdentifier:

Creating a class with no init method (Objective-c)

Is it possible to create a class with no init method so as to force all callers to create the object with a factory method instead?
So basically, you want to make sure that your class is never initialized using -init, right? You can't do exactly what you want to do, but you can come close.
Since you inherit from NSObject, you have an init method and there's nothing you can do to prevent it from being called. That said, you could override init to this:
- (id)init
{
[self dealloc];
#throw [NSException exceptionWithName:#"MyExceptionName" reason:#"Reason" userInfo:nil];
return nil;
}
This way, anytime someone calls your -init method, it kills the object, so practically speaking, your init method is pretty much un-callable.
If you really wanted to cause trouble for users of your class who use init, you can do:
#implementation MyClass
- (id) init
{
// Still have to make sure the runtime has initialised everything for "self"
self = [super init];
if (!self) return nil;
[self release]; // some say you should use [super dealloc]
[super doesNotRecognizeSelector:_cmd];
return nil;
}
#end
You invoke super's doesNotRecognizeSelector: because you might want to implement your own behaviour for unrecognised selectors for your class.
Depends. If you have your class inherit from NSObject, it will have the inherited init method (which does nothing to your instance variables). So in that sense, even if you really really wanted to not have an init method, you'd most likely still have one. So if your question was "Do I need to implement a trivial init method?", the answer is "no, you don't need to". However, if your question was "Do I need to call the init method if I didn't override it?", then the answer is "yes, you do". Whatever you do with NSObject subclasses, at some point you still need to call init after the object is created. Such is the way of life.
That being said, you most likely want an init method, unless your object initialization requires nothing more than zeroing your whole object.
Otherwise, if you choose to not inherit from NSObject or any of its subclasses and just inherit from nothing, which is clearly a bad idea because of how the NSObject class deals with everything the ObjC runtime needs to do and the requirements are quite high, then you'll potentially end up with no init method at all. But seriously, don't try this at home.
Sure. In Objective-C, there are no actual constructors. init-type methods are typically used to initialize a class, in the same vein as a constructor, but they're just a "normal" method (there's nothing special about them like there are with, e.g., Java constructors).
That said, unless your class does no initialization for its instances, you probably want to have some sort of init method.
NSObject implements an init method for you that does whatever it does. If your class has nothing to setup when it's instantiated then simply do not override the -(id)init method provided by NSObject. But you still call it when you create the instance.