I understand the purpose of having an initializer is to set the instance variables to certain values. However, I am confused as to why you would want to have multiple initializers for each instance variable. Can't one initializer set all the instance variables? I guess my question really is what is the practicality of having multiple initializers in a class. For instance a class has the following:
- (id)initWithItemName:(NSString *)name
{
return [self initWithItemName:name valueInDollars:0 serialNumber:#""];
}
Meanwhile the designated initializer is given as such:
- (id) initWithItemName:(NSString *)name valueInDollars:(int)value
serialNumber:(NSString *)sNumber;
The designated initializer, as you can see, already initializes the itemName variable. So, whats the pont of having a specific initializer just for one variable.
Default values. If you use the designated initializer with a default value that you have to specify each time, it can be a pain if you want to change this default value because you would have to go to every instance of this initializer and change the value. If you have an initializer that centralizes the location of the default value, it's easy to change.
Deprecation. If you have to add a variable to the class and to the initializer later on, then it's much easier to not have to change every place that initializes the variable when you don't need to specify a value.
Related
I know objective c has built in 'init' method to initialize object. But i want to know In what circumstances do i need my own initializes to initialize object?
I want to know what value is assigned to self when i invoke 'self = [super init]'
You only need your own initializer when you need your object to default to a state that is different than what the compiler will enforce. That is, all instance variables are initialized to 0 (for integer-like types) or 0.0 (for floating point types). That means all pointers are nil and all numbers are 0(.0). If you need to initialize anything to a different value (creating internal container objects, for example), you need your own initializer.
Similarly, if your class inherits from a class that implements its own initializer, you only need your own if you want your state to be different than the superclass's.
Now i have had this problem clouding my mind for quite sometime and i really need someone to clarify this for me.
1) what is a unique identifier that causes the init method to return a different object other than the one you were initially trying to allocate with the call?
.. What should you do in such a case?
2) When a designated initializer from one class assuming that class has more than one method, invokes the designated initializer in its parent class consequently invoking NSObject's init method; what exactly is happening when the parent class init method is invoked? what is "self" in that method explicitly referencing to, as well as the "self" returned from its root class?
Maybe this will answer your questions:
An init method is just a method like any other, there is nothing special about them per se;
Method parameters are local variables which are assigned an initial value, that value being the one given in the call;
self is a hidden method parameter, a value for it is passed in the call as with all other parameters;
The result of the method is implicitly marked with the ns_returns_retained attribute; and finally
The self parameter is implicitly marked with the ns_consumed attribute.
The attributes mentioned effect how ARC manages the references returned (ns_returns_retained) by, or passed to (ns_consumes), a method. These attributes can be explicitly applied to any method.
The attribute ns_returns_retained is applied implicitly to methods in the alloc, copy, init, mutableCopy, and new families; while ns_consumes is implicitly applied to the hidden self parameter of init methods.
The ns_consumes attribute is the only "unusual" feature of init methods. It tells ARC that the method being called takes ownership of the passed object reference, and hence is responsible for releasing it when required. So in the common statement found in init methods, a call to the superclass init method:
self = [super init];
the current reference stored in self is passed to the called method along with the callers ownership of that reference. When the result of the call is assigned back to self ARC does not need to relinquish ownership (aka "release") the old reference stored there - ownership was already passed to the called method - or take ownership (aka "retain") of the new reference - as the called transfers its ownership back to the caller.
The above allows an init method to return a different reference than the one it was passed, and releasing the one it was passed. This feature is not commonly used in user classes but a number of common system classes, e.g. NSString and NSNumber, take advantage to reduce the number of objects needed.
The above sounds more complicated than it is! If you have specific questions then ask new specific questions as #MichaelDautermann suggests in the comments.
HTH
Addendum
In response to comments maybe the following will help. All code typed directly on an iPad, expect errors!
How does the following method work?
- (NSString *) doSomething:(NSString *)aLocal
{
aLocal = [super aLocal];
return aLocal;
}
In the call:
NSString *someResult = [someObjectRef doSomething:someLocalVariable];
where someObjectRef is a variable holding a reference to an object that declares the above method, and someLocalVariable holds a reference to a string.
In outline it is:
a new method invocation is created along with its local variable aLocal
the reference stored in the callers someLocalVariable is copied (it's value not the object it references) and stored in aLocal
the statements of the method are executed
the first statement is a call to the same method implemented in the super class, the value of the reference in aLocal is passed to this method, and the reference returned by the call is stored into aLocal - replacing the reference previously stored there.
the second statement returns the value of the reference stored in aLocal as the method result, and that reference is stored into the caller's someLocalVariable.
None of that should be surprising, and the reference return is probably not the reference passed in (it could be, we've no idea what the inherited doSomething method does, it may just return what it was passed).
Now all you have to understand is that self is an implicitly passed parameter. What that means is the above method is effectively declared as:
- (NSString *) doSomething:(NSString *)aLocal selfRef:(instancetype)self
and Objective-C automatically supplies the reference passed as selfRef and stored into the method's local variable self.
Finally changing the name of doSomething to, say, initAndDoSomething changes the way ARC automatically handles the references passed as self and the one returned to ensure no unwanted objects get left lying around - this is done by implicitly adding the attributes mentioned in the original answer.
That's it, init methods are just methods. Don't think of them as special, it inflates their ego ;-)
HTH
I am trying to understand the methods generated when properties are used.
Say I have the following declaration
#property int myint;
Now I know I could access this variables as such (say d was my instance of the class)
d.myint = 12; //this is equivalent to [d setMyint:12];
NSLog(#"The value is %d",d.myint); // what method is generated ?
What is the getter method called ? I was under the impression it was called getMyint however that isnt available ? Any suggestions if I might be missing something here?
As stated in the other answers, the proerty declaration gives you a getter and a setter for that instance variable for free! The notation is that you can either get [self myInt]; or self.myInt;. Both calls are 100% equivalent, i.e. they will both call the method - (int)myInt. This method is not visible (or rather, it's not explicitly implemented, see below) by default, however, you can implement it to provide some custom logic (e.g. check for specific values, error handling or lazy instantiation). If you want to override it, put this in your .m file.
- (int)myInt {
NSLog(#"getter of my int called, current value %d", _myInt);
return _myInt;
}
I only want to add to the the previous answers that in Objective-C, you have the possibility to rename your getters and setters when declaring the property, like so:
#property (getter=getMyInt) int myInt;
you can call those in the exact same way that you would use your normale getter:
int myInt = [self getMyInt];
// or
int myInt = self.getMyInt; // (will work but is not recommended since the compiler will interpret this as calling the getter of a property named `getMyInt` and only when this one is not found will actually fall back to the custom getter (thx to #NikolaiRuhe again for pointing this out))
Update:
Agreeing with most of what #NikolaiRuhe stated in his comment, here is a clarification of my answer referring to the mentioned issues:
This is indeed a typo, of course the way to use the property getter is by either calling [self myInt] or using dot notation self.myInt, and not [self getMyInt]. These calls are however 100% equivalent since they both invoke the actual getter.
About the visibility, indeed I should have been more explicit here. In OOP terms, visibility is a concept that describes the accessibility of instance variables from the outside of a particular class. I meant it exactly in the way that #NikolaiRuhe suggested, i.e. that this method is not explicitly implemented (so, it's not visible in the code by default). Sorry about this misunderstanding!
I am actually not sure about this point. For me this didn't make much of a difference in the past, I don't insist on this point. So I'd well acknowledge that the act of explicitly implementing a getter is not actually an override but rather a replacement of the synthesized method.
After explicitly renaming the getter to getMyInt like I suggested above, I don't see anything "wrong" with calling self.getMyInt. Why would this be the wrong way to access the property?
The getter method would be:
[d myInt];
Per the Apple docs :
You access or set an object’s properties via accessor methods:
NSString *firstName = [somePerson firstName];
[somePerson setFirstName:#"Johnny"]; By default, these accessor methods are synthesized automatically for you by the compiler, so you
don’t need to do anything other than declare the property using
#property in the class interface.
The synthesized methods follow specific naming conventions:
The method used to access the value (the getter method) has the same
name as the property. The getter method for a property called
firstName will also be called firstName.
The method used to set the value (the setter method) starts with the
word “set” and then uses the capitalized property name. The setter
method for a property called firstName will be called setFirstName:.
The syntax of getter method would be-
-(int)myint{
return myInt;
}
It will return myInt property of the receiver if this message i.e. d in your case.
If you are creating a property in objective-c, it creates 3 things for you.
an instance variable which you can access by using an underscore before the property name. Ex: _myint
a getter method which you can call directly by using the property name. Ex: [self myint]; / self.myint, this will actually call - (int)myint {} method.
a setter method which you can call by using a 'set' keyword before it. Ex: [self setMyint:12]; / self.myint = 12, this will actually call - (void)setMyint:(int)myint {} method.
Source
So when you write d.myint = 12; this is equivalent to writing [d setMyint:12];
And when you write NSLog(#"The value is %d",d.myint); this is equivalent to writing NSLog(#"The value is %d",[d myint]);
Custom Getters and Setters
Credits
You can also give custom names to your property Getters and Setters. This is how it is done
#property (getter=getMyInt, setter=setMyIntWithInt) int myint;
Ex:
[d setMyIntWithInt:12]; //This will set the instance variable to 12.
NSLog(#"The value is %d",[d getMyInt]);
Also, you can override these methods in your implementation(.m) file for error handling or lazy instantiation.
I'm reading an Objective-C book and I have a question that the book doesn't seem to really answer.
Let's say I have two custom-made classes.
The first class is called ClassA. It has both the .h and .m files of course. The second class is called ClassB. It also has both .h and .m files.
Somewhere in the code, 'ClassA' has this method:
-(IBAction)displaySomeText:(id)sender {
ClassB *myNumber = [[ClassB alloc]init];
NSString *numberString = [myNumber storedNumberAsString];
// storedNumberAsString is just a method that returns a string object that holds
// myVariable.
[textView insertText:numberString];
//textView is a object I created that just displays some text on screen.
[myNumber release];
}
The book tells me that ClassB should have a method:
-(id)init {
[super init]; //I know why this is done, the book explains it well.
myVariable = 42; // I created this variable already in the ClassB .h file
return self;
}
Now, when in the Interface Builder I click the buttons I connected, etc. It works, the number displayed is 42.
My question is, why do I have to create an -(id)init method for ClassB, if I can do the following in ClassA's method:
-(IBAction)displaySomeText:(id)sender {
ClassB *myNumber = [[ClassB alloc]init];
myNumber.myVariable = 42; //I just do this to skip the -(id)init method.
NSString *numberString = [myNumber storedNumberAsString];
[textView insertText:numberString];
[myNumber release];
}
Doing this, it still displays the same value: 42. I can change it to whatever I like. So why not just use the init inherited from NSObject and just do the simple way myNumber.myVariable = 42?
Suppose that the value of the instance variable were something more complicated than an integer. Suppose it involved reading a string from a file, or getting some information over the network, or just doing some arithmetic. In that case, it wouldn't make sense to have ClassA be responsible for setting that value correctly. That would break the encapsulation that makes it useful to have separate classes in the first place.
In this extremely simple case, you're quite right, there may be no reason to have a custom initializer for ClassB, but in general, a class should itself be responsible for its state being set up correctly. Foisting that responsibility off on other classes means that those others need to know about the internals of the first, meaning the two may be too tightly coupled.
In some cases, the value of the ivar might be a piece of information that is known only to ClassA, or needs to be calculated based on such a piece of information. Then you should create a custom initializer for ClassB which receives that value, e.g., - (id) initWithInteger: This would become the "designated initializer", and you would then override -[ClassB init] to call it with some reasonable default value.
If instances of ClassB do not have to have anything initialized (other than to nil/zero), you do not need to create an explicit init method for ClassB. In this case the question is whether setting myVariable to 42 is ClassB's answer to life, the universe, and everything, or whether myVariable is just a field in ClassB that could be set to any value.
That is, the issue is conceptual, not of physical significance. If conceptually the value 42 "belongs" to ClassB, then there should be an init method for ClassB that sets it. If that specific value has more meaning to ClassA than to ClassB then some method of ClassA should set it. If you do it "wrong" the code still works fine, but your design is slightly less elegant, slightly less extendable, slightly less robust.
This is kind of a tricky issue. I was "brought up" to think that after a constructor (initializer) runs, the object should be ready to go. You should be able to safely call any method on it. Therefore, you need to set up any instance variables in the constructor for which 0 is not a valid value. I like to set them up if they have 0 values anyway, just for sanity, because I never want to bother to know the minute details of every language I work with, like whether they initialize instance variables to 0 automatically.
However, there are some arguments for not initializing some variables.
The initialization is complex, like loading a file or getting data from the network. You want to keep open the possibility of creating an instance and waiting until you're ready to do heavy weight operations.
There are quite a lot of instance variables that are configurable. Your options are to make a constructor with umpteen arguments, or make a constructor with no or a few arguments, and let the caller decide which values should be set to non-default values by property setters.
You need to set up a whole object graph before you can meaningfully initialize a value. That is, initializing the value might have side effects that depend on other related objects. The best solution is to construct each object, then use property setters to set the relationships between objects, then use property setters to initialize attribute values.
I have seen code like that in the Application delegate in iPhone project for example.
what is the variable with the underscore means? can I use it as setter and getter for the variable?
also when releasing the variable should I use:
[variable release];
or
[_variable release];
Thanks.
In some coding conventions the underscore before instance variables is used to be able to quickly differentiate them from other variables. It also helps avoid naming conflicts with local variables in methods and subclass methods.
#synthesize variable = _variable
Creates a setter and getter that set/get the variable you set it to in this case _variable. So outside access uses code like object.variable which is really just returning _variable. however the class usually uses the _variable internally.
#synthesize variable = _variable;
The property name is "variable" and the instance variable that backs it up is named "_variable". You should use the accessors -variable and -setVariable: rather than accessing the ivar directly, except in -init and -dealloc, where you'd use _variable.
In your example variable is a property and _variable is an instance variable. For simplicity sake we can say that by synthesizing you are essentially instructing that the property ( in our case variable) will use the instance variable ( in our case _variable) for storing and retrieving values. What you are really doing is instructing the compiler to create implementations that match the specification given in the property declaration.
The suggested way of releasing when you are using a property will be to just assign it nil. This would essentially release the object and also set the instance variable to nil instead of being a dangling pointer.
If you were not using property then you can call the release on the instance variable and then ideally you want to set it to nil.