This question already has answers here:
What is the purpose of the -self method in NSObject-conformant classes?
(3 answers)
Closed 8 years ago.
I was messing around with Objective-C and I stumbled upon something strange. The following code compiles and works the way I want it to.
self.scrollView.delegate = self.self.self.self.self;
// equivalent to = self;
Why does this compile? Is it the case that self is a property of an object. If so, I have never seen self declared as a property. I thought self referred to the instance of the class you are creating.
Let me turn this around Why shoudn't it compile nor work as expected?
self is a property of NSObject. It always points to the object itself. Every object inheriting from NSObject has it.
As you say, self refers to the instance. Well, it is not only valid in the context of creating instances. It is always there. And it is very helpful.
[self myProperty] or self.myProperty refers explicitely (laugh more or less explicitely but it does) to the getter (or the setter) of the property myProperty while just typing myProperty within a method refers directly to the property without passing the getter.
Another example is someOjbect.delegate = self; or so.
So, as self alsways refers to an object, to the very object, it has a self property that refers to the very object which has a self property ...
BTW, classes are objects in Objective-C that inherit from Class. In the context of a class, i.e. in class methods, it refers to the class object of the very class. You can play the same game there. If you start off with an instance, then you can play the game with the class property.
self.class.class.class == [self class].self.class.self
should evaluate to YES. (Well, I never tried that myself. If you actually try it and find this wrong, then please let me know)
self is a method in the NSObject protocol. It returns the object it is called on, it is rather pointless.
This is distinct from the local variable self, which within a method refers to the object the method was called on.
Both the method and the local variable apply to class objects as well as standard instances, so a class method has a self local variable and a class object a self method.
Related
This question already has answers here:
Difference between self.ivar and ivar?
(4 answers)
When should I use the “self” keyword?
(6 answers)
Closed 8 years ago.
I know instance variable and property. I often see people init a UILabel like this
self.label = [[UILabel alloc] init]; //and
_label = [[UILabel alloc] init];
So, what's the difference between using self.label and _label to set a object?
The difference is simple: Using self.label = [[UILabel alloc] init] will actually invoke the method [self setLabel:[[UILabel alloc] init]], and using _label = [[UILabel alloc] init] will directly assign the value to the instance variable.
In practice what this means is that using the dot syntax is usually the best as the method invoked probably handles a lot of stuff for you, including:
Memory management: For example, if you declare a property with attribute 'strong' or 'retain', then the method invoked should retain the object assigned.
Key-Value Coding notifications: Maybe the class is key-value coding compliant for the property, which means the invoked method will notify the changes to observer objects.
Why would you not use the dot syntax? There are two potential reasons:
To avoid side effects: A good practice is to not use the dot syntax inside an initializer method. This is because we want to assign the value but don't want the other side effects of the invoked method for safety reasons.
Performance: This is probably rare, but maybe you are trying to implement a method with high performance and using instance variables directly can save the cost of invoking a method.
If you want to know more, I recommend reading this iOS guide which describes in more detail the ideas I mention here.
The difference is that:
the names with _variable are instance variables.
self.variable is calling a getter method on your object.
In your example, the instance variables are automatically generated and you don't need to synthesize your properties either.
The real important difference in your example comes into play if you are not using ARC-
self.variable will retain an object for you if you mark the property with retain or strong _variable does not address memory management at all
In your example, self.label would call the getter method 'label' on self -- this is equivalent to calling [self label]. _label is the backing store for the class instance property -- i.e. an instance variable, no different than accessing a standard variable directly. There is no getter method wrapped around it.
The difference is very, very important, because you are able to override the getter/setter methods for properties. You may wish to do this, for e.g., if you would like to bundle some behavior change with the state change of the variable. Calling the getter or setter maintains this behavior. Calling the getter also retains the variable.
Basically, unless you know why you're preferring to class _label in any particular instance, stick with the getter self.label. One case where you may want to use _label is during initialization, where you need to set a happy default w/o behavior the getter may bring with it.
The difference is that using _label is accessing the instance variable (ivar for short) directly, where as using self.label is actually calling [self setLabel:[[UILabel alloc] init]];.
Calling the setLabel: method does other things, such as possibly retaining the variable (depending on how the property was declared), but can also trigger other side effects as set up in your setLabel: method. Those side effects could be something like data validation, or could perhaps sync that value to a server.
Is it possible to initialize a property in a category?
For example, if I have a mutable array property called nameList in a class. Is it possible to have a category created for this class to add an object to the array property before any of the category method is called?
If I understand you correctly, and others are interpreting your question differently, what you have is:
A class with a property
A category on that class
And you want to call a particular method automatically before any category method is called on a given instance, that method would "initialise" the category methods by modifying the property.
In other words you want the equivalent of a subclass with its init method, but using a category.
If my understanding is correct then the answer is no, there is no such thing as a category initializer. So redesign your model not to require it, which may be to just use a subclass - as that provides the behaviour you are after.
The long answer is you could have all the category methods perform a check, say by examining the property you intend to change to see if you have. If examining the property won't determine if an object has been "category initialized" then you might use an associated object (look in Apple's runtime documentation), or some other method, to record that fact.
HTH
Addendum: An even longer/more complex solution...
GCC & Clang both support a function (not method) attribute constructor which marks a function to be called at load time, the function takes no parameters and returns nothing. So for example, assume you have a class Something and a category More, then in the category implementation file, typically called Something+More.m, you can write:
__attribute__((constructor)) static void initializeSomethingMore(void)
{
// do stuff
}
(The static stops the symbol initializeSomethingMore being globally visible, you neither want to pollute the global name space or have accidental calls to this function - so you hide it.)
This function will be called automatically, much like a the standard class + (void) initialize method. What you can then do using the Objective-C runtime functions is replace the designated initializer instance methods of the class Something with your own implementations. These should first call the original implementation and then an initialize your category before returning the object. In outline you define a method like:
- (id) categoryVersionOfInit
{
self = [self categoryVersionOfInit]; // NOT a mistake, see text!
if (self)
{
// init category
}
return self;
}
and then in initializeSomethingMore switch the implementations of init and categoryVersionOfInit - so any call of init on an instance of Something actually calls categoryVersionOfInit. Now you see the reason for the apparently self-recursive call in categoryVersionOfInit - by the time it is called the implementations have been switched so the call invokes the original implementation of init... (If you're crosseyed at this point just draw a picture!)
Using this technique you can "inject" category initialization code into a class. Note that the exact point at which your initializeSomethingMore function is called is not defined, so for example you cannot assume it will be called before or after any methods your target class uses for initialization (+ initialize, + load or its own constructor functions).
Sure, it possible through objc/runtime and objc_getAssociatedObject/objc_setAssociatedObject
check this answer
No it's not possible in objective c.Category is the way to add only method to an existing class you can not add properties in to this.
Read this
Why can't I #synthesize accessors in a category?
I'm was playing around with the standard sample split view that gets created when you select a split view application in Xcode, and after adding a few fields i needed to add a few fields to display them in the detail view.
and something interesting happend
in the original sample, the master view sets a "detailItem" property in the detail view and the detail view displays it.
- (void)setDetailItem:(id) newDetailItem
{
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
i understand what that does and all, so while i was playing around with it. i thought it would be the same if instead of _detailItem i used self.detailItem, since it's a property of the class.
however, when i used
self.detailItem != newDetailItem
i actually got stuck in a loop where this method is constantly called and i cant do anything else in the simulator.
my question is, whats the actual difference between the underscore variables(ivar?) and the properties?
i read some posts here it seems to be just some objective C convention, but it actually made some difference.
_property means you are directly accessing the property.
self.property means you are using accessors.
In your case, in the setter method you are calling it, creating a recursive call.
In the course of your experiment, you've set up an endless loop which is why the simulator goes non-responsive.
Calling self.detailItem within the scope of setDetailItem: calls setDetailItem: recursively since your class implements a custom setter method for the property detailItem.
I would refer you to the Apple documentation on declared properties for the scoop on properties, ivars, etc; but briefly, declared properties are a simplified way of providing accessor methods for your class. Rather than having to write your own accessor methods (as we had to do before Objective-C 2.0) they are now generated for you through the property syntax.
The properties are basically a way of the compiler to generate a setter and getter for a given instance variable.
So when you use something like:
id detailItem = self.detailItem;
what you are doing under the hood is:
id detailItem = [self detailItem];
Same for:
self.detailItem = otherDetailItem;
would be:
[self setDetailItem:otherDetailItem];
So when you write the setter yourself.. you get in an infinite loop since you access the method itself in itself.
You can freely make use of the 'self.' notation in your class, just not when you're overriding the setter or accessor because of the mechanism I described above.
Cases in a class where I use the . notation over simply accessing the ivar is when I change the value, you never know inside your class what needs to happen when you change the value. do you have something in terms of a status that should notify some delegate that a status changed? Usually this is not the case, however, just by using the . notation you are making sure that in the future you won't have to refactor some code if you did decide to do some magic in your setter method.
I'll make an example (without ARC enabled):
#property (nonatomic, retain) NSNumber* number;
If you don't synthesize it, you can access it this way:
self.number= [NSNumber numberWithBool: YES];
This case the number is retained.If instead you synthesize it and don't use the property:
#synthesize number;
Later in the file:
number=[NSNUmber numberWithBool: YES];
You haven't used the property, so the number is not retained.That makes a relevant difference between using accessors and synthesized properties.
I have class named 'WebServicesiPhone' .... I want to create an instance of this class and do some json parsing functions and store the result contents into some arrays in the Delegate class ...
how can I declare an instance of this class in some other class ....which is the best way ....
WebServicesiPhone *newsParser = [[WebServicesiPhone alloc] init];
[newsParser getData:0:nil:0:0];
[newsParser release];
or i have to declare a instance in other class's .h file .. like this
WebServicesiPhone *newsParser;
and allocate in method file .. if i am using this method whrere i have to release the object after my use .....
newsParser = [[WebServicesiPhone alloc] init];
I think you're mixing some terms so I'll try to explain as simple as possible.
WebServicesiPhone *newsParser; is not an instance, it's a variable. If declared in .h file between curly braces, it's an instance variable, as every instance of your class will have one. If it's declared somewhere in .m file, it's a local variable and will only be available inside the block of code where you declared it.
[[WebServicesiPhone alloc] init]; instantiates a new object of type WebServicesiPhone, also called an instance, and when you assign value of that to newsParser, be it instance or local variable, it (newsParser) becomes a pointer to your class' instance.
So if you have to use this newsParser all around your code, best practice is to create an instance variable for it (or even a property) and release it in your class' dealloc method. If you only need it inside one block of code, for example inside init method implementation, just create a local variable and release it right there once you're done with it.
It all depend if you want to expose the instance publicly. If you don't need that, use local variable as you do in the first sample.
If you use the other method, release the instance in the dealloc method of your class.
If you want the instance variable of WebServicesiPhone to have class scope and as VdesmedT said if you want to expose the instance variable publicly.You can hide from exposing it publicly by not declaring it in .h but class extension in .m to have class scope. Release it after you are done with it. Usually in dealloc, but lets say you alloc init this instance in a - (void)createWebService and call it over and over again then dealloc'ing it in dealloc method of class isn't proper memory management.
In my controller class, I initialize two instances of a model class (whose header is properly imported into controller class) with an NSButton. The model is really simple, just 4 members and one method - attack(). Making a silly text game!
- (IBAction)startGame:(id)sender {
Combatant *hero = [[Combatant alloc] init];
Combatant *enemy = [[Combatant alloc] init];
[console insertText:#"You have created a hero! An enemy approaches...\n"];
}
So now I have these two objects sitting there. Or do I? Because this other button, the one that's supposed to make them fight, has no idea what hero and enemy are, or that they have a class method that makes em' fight!
- (IBAction)attack:(id)sender{
[hero attack:enemy]; //Use of undeclared identifier, blah blah.
[console insertText:#"You attack the enemy! Woah!\n"];}
I get that if I initialized those objects in the attack method, then I could use them, so I gather this is something to do with scope. But I don't like the idea of sending model objects to controller methods, that seems silly.
Let me apologize: yes, this is a stupid, high-level question about the structure of Cocoa. Sorry. But I figure one of you will know exactly what I am not doing and tell me to do it!
In short, what is the Cocoa way of doing things in this situation? Thanks in advance.
-Alec
When you declare a variable in a method, it is a local variable, which means it only exists in that method. The same goes for variables you declare in functions.
If you want the variable to exist in all instance methods in the class, you need to make it an instance variable, which you do by declaring it in that { … } section in the class's #interface.
Note that any objects you store in instance variables, the instance should own. This means three things:
You'll need to either retain the object (and thereby own it) or make a copy (which you will then own) before assigning it to the instance variable.
Since you own it, you'll need to release it in the instance's dealloc method.
If you decide to replace it with a different object, you'll need to release the former object (since you still own it) and retain or copy the new object (in order to own it).
See the Objective-C Programming Language and the Memory Management Programming Guide for more information.