Objective-c Is super init a class method or instance method? - iphone

I am new in objective c. I understand that -init() is an instance method and return an object
e.g. myObj=[myObj init]; will return an object myObj.
However, if self =[super init]; normally super refer to parent class e.g. NSObject which is a class, not instance.
So, Is -init() instance method or class method for super init?
thanks

init is an instance method. The fact that you call it on super does not change it.
Keep in mind that super does not represent the class of your object, but your object seen as an instance of its parent class in the class hierarchy.
And you never call myObj=[myObj init]; — you call myObj = [[MyObj alloc] init]. Notice the case difference between myObj (a variable) and MyObj (the class of which this variable is an instance).

Generally init is used after alloc in this way:
MyObject* obj = [[MyObject alloc] init];
and alloc create the object instance, so init is an instance method, and when you override it, it's good habit to call always the parent class init.
Try to read this article.

Super is referring to the methods of the parent class in the current object. Calling super init will call the method init on the current object (self), but will use the implementation of the super class. So no - init is not a static method (this would be visible due to a + before the init method). you can call super whatMethodYouWantFromSuperclass even though it is not static. Static methods are not called on an object (self) but on a class ([NSObject yourStaticMethod]).

Related

Link superclass init method to designated initializer

Since every class inherits the initializer from the superclass this is how I have linked
the default implementation of init to its designated initializer. (It's working.)
Link:
-(id)init {
return [self initWithItemName:#"Default Value"
valueInDollar:0
serialNumber:#""];
}
Initializer:
-(id)initWithItemName:(NSString *)myItemName
valueInDollar:(int)myValueInDollar
serialNumber:(NSString *)mySerialNumber;
My question is, do I ALWAYS have to link my own initializer the way I did it (Link)?
So WITHOUT the code below own initializers would never be called? Am I right?
-(id)init {
return [self myInitMethod......"];
}
If you only initialize your object with initWithItemName, then you don't have to define the init method at all. The initializers are just ordinary methods (no magic involved), so what you call is what will be invoked. But it is good practice to implement the init method so it can be called and the object will be in a consistent state.

Instance method unable to read class instance variables

Problem: Variables from a class are being overlooked somehow when the method is called from a different class.
Basically: I have Class A, Class B. I also have Method A, Method B each in their respective classes.
When calling Method A from Class B Method B, I can NSLog values fine, however I cannot access an NSMutableArray contained within Class A. There is my issue.
// Class B
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
foodListingObj = [[FoodListing alloc] initWithNibName:#"FoodListing" bundle:nil];
}
return self;
}
- (void)toggleImage //Method B in Class B {
[foodListingObj didToggle:self.indexOfToggledCell];
}
// Method in Class A
- (void)didToggle:(NSIndexPath *)toggledIndexPath{
//[_toggledIndexArray addObject:toggledIndexPath];
[_toggledIndexArray addObject:#"Anything"];
}
// Method in Class A
- (void)checkArray{
// Log the count of the array
// it always says 1 because I intialize the array
// then add an an object like so [_toggledIndexArray addObject#"hi"];
// in my ViewDidLoad Method. Hence it appears that the array is still around
// (not deallocated), but yet my method cannot seem to touch it...
NSLog(#"%i",[_toggledIndexArray count]);
}
// dealloc for Class A
- (void)dealloc{
// I release the array among other things
[_toggledIndexArray release];
}
The array (_toggledIndexArray) is a property declared in the header, and is initialized in Class A's viewDidLoad with
_toggledIndexArray = [[NSMutableArray alloc] init];
The error is the fact that Method A does not seem to affect the array for a reason unknown to me.
From the code above, it looks like your problem is that you are creating a new instance of FoodListing each time your toggleImage method is called.
Is this really what you intend to do? If it is, ViewDidLoad isn't going to get called in this case, since you are just allocing and initing the view controller as opposed to using initWithNibName, so unless you are doing something in your custom loadView method, there isn't going to be a view that is loaded.
However, I don't expect you do want to create a new instance each time, the implication from your code is that the FoodListing object already exists and has the array populated already.
So, in whatever "class b" is, declare a property of type FoodListing. Set this to your FoodListing view controller (this will be either when class b is created or presented, or when the FoodListing object is first created, you havent given enough context for me to say). Call the methods on the object held in the property instead of creating a new one.
You need to maintain the FoodListing object in Class B as class variable and not always alloc/init it in toggleImage function. Perhaps do
if(self.foodListing==nil) { //alloc/init it}else{ //do your thing here.}

+(void) initialize in objective-c class static variables constructor

I found some sample code from here.
static UIImage *backgroundImageDepressed;
/**
*
*/
#implementation DecimalPointButton
+ (void) initialize {
backgroundImageDepressed = [[UIImage imageNamed:#"decimalKeyDownBackground.png"] retain];
}
Is it something like this - +(void) initialize method initialize static variables of a class ( interface ) in Objective C? I have never seen this before.
This +initialize method is described in The Objective-C Programming Language.
The runtime system sends an initialize message to every class object before the class receives any other messages and after its superclass has received the initialize message. This gives the class a chance to set up its runtime environment before it’s used. If no initialization is required, you don’t need to write an initialize method to respond to the message.
For example, when [DecimalPointButton alloc] is called, the runtime will check if [DecimalPointButton initialize] has been called. If not, it will +initialize the class. This ensure the backgroundImageDepressed image is ready before any instances of DecimalPointButton are constructed.

-(id)init using designated initialiser?

In the past I have always used method_1: but I have recently noticed a few instances where folks have instead called the superclasses designated initialiser. Does it matter, just curious if its more about style or substance?
Method_1:
-(id)init {
self = [super init];
if(self) {
//do things ...
}
return self;
}
Method_2:
-(id)init {
[super initWithNibName:nil bundle:nil];
// do things ...
return self;
}
-(id)initWithNibName:(NSString *)nibName bundle:(NSString *)bundle {
return [self init];
}
cheers Gary
Only a few instances?
The Apple documentation on Designated initialisers has this to say on subclassing:
General Principle: The designated initializer in a class must, through a message to super, invoke the designated initializer in a superclass.
Also:
Designated initializers are chained to each other through messages to super, while other initialization methods are chained to designated initializers through messages to self.
Your method 2 would be correct if:
-initWithNibName:bundle: is the designated initialiser of the super class
-init is the designated initialiser of your class (your example is a bit bizarre since you deliberately throw daway the nib name and bundle parameters)
-init was correctly coded not to throw away the return value from [super initWithNibName: bundle: ]
In your class you have to cover all of the super class init methods to ensure that your designated initialiser ultimately gets invoked.
Neither of the above make any sense for the init methed of a class who's super class has the designated initializer
- (id)initWithNibName:(NSString *)nibName bundle:(NSString *)bundle
What are you trying to do?
The idea of a designated initialiser is that all other initialisation functions of a class should call it (this is only enforced by convention). This is nice as it means that someone writing a subclass can add additional steps to the initialisation while only overriding a single initialisor. When this pattern is being used, method 1 should only happen when init is the designated initialiser. One strategy for ensuring this occurs is as follows:
Suppose C inherits from B and let the designated initialisers be d_c and d_b. We override d_b in C to make it simply call d_c on itself. Since d_b is called by all other initialisers of B, this ensures that all initialisers present in the subclass call d_c. We then make all new initialisers call d_c too. d_c calls d_b in its superclass B, which will then pass the calls further up the chain.
Note that this strategy is the opposite of how classes are often initialised. For example, an initialiser with arguments a:1 b:2 could handle the b argument and then call another initialiser that could handle just the a argument. This works well when the function with arguments a and b is simple, by the designated initialiser works better in more complicated situations.

Adding a decorator to a class derived from NSManagedObject

I'd like to add additional behavior to a class derives from NSManagedObject and there are 4 distinct (for now) groups of behaviors. I don't need my decorator class to be persisted with CoreData -- it's purely for adding run-time behavior.
However, if I try to apply the standard Decorator pattern, I can't call '[super init]', which makes sense because you need to insert the new object into the ManageObjectContext. But I thought you'd want to invoke [super init] within WindowClassScrollDecorator's init and likewise, later 'dealloc' so everything gets initialized & cleaned up correctly.
I'm inheriting from 'MyWindowClass' class because I don't want my client classes to know the subtype but depending on the decorator used, the behavior will be different.
So what's a good way to approach this?
#interface MyWindowClass : NSManagedObject
{
}
#end
#interface WindowClassScrollDecorator: MyWindowClass
{
MyWindowClass *decoratedClass;
}
- (id)initWithMyWindowClass:(MyWindowClass *)aWindowClass;
#end
#implementation WindowClassScrollDecorator
- (id)initWithMyWindowClass:(MyWindowClass *)aWindowClass
{
// Calling [super init] elicits the following error:
// Failed to call designated initializer on NSManagedObject class 'ModelClassScrollDecorator'
if (self = [super init])
{
// do some initialization work here
self.decoratedClass = aWindowClass;
}
}
#end
The lifecycle of NSManagedObjects is a bit different from that of other objects; specifically, the object may turn into a fault (essentially a shell object without any of its properties set) without being deallocated. You should be sure to be aware of these events, so you may want to look at the NSManagedObject Class Reference - Subclassing Notes document. Specifically, you may want to look into awakeFromInsert:, awakeFromFetch:, and (will|did)TurnIntoFault.
To address your immediate issue, an NSManagedObject cannot be created without an NSManagedObjectContext to live in. Thus, to initialize a managed object, you must call its designated initializer:
initWithEntity:insertIntoManagedObjectContext:
Your init method needs to call that method on the superclass or else your NSManagedObject won't work.
The question you have here seems to not be CoreData specific but OO design.
You shouldn't be inheriting NSManagedObject if it is not a NSManagedObject.
You should make MyWindowClass either be a protocol, or a class which has a NSManagedObject.