aclass.h
@interface aClass : NSObject {
NSString *name;
}
@property (nonatomic, retain) IBOutlet NSString *name;
@end
aclass.m
@implementation aClass
@synthesize name;
- (void)dealloc {
[name release];
[super dealloc];
}
- (void)test1 {
name = @\"hello\";
}
- (void)test2 {
self.name = @\"hello\";
}
Take above as an example. Could someone please explain the difference between name = @\"hello\"
and self.name = @\"hello\"
? Thanks!
EDIT: Follow-up question: How to write my own setter for an ivar, i.e.: self.ivar = ...?
BE AWARE, THIS POST IS OLD !
This post is from the previous decade.
Be sure to read the important footnote down below, cheers!!
It\'s really difficult to understand all this, when you\'re just getting started.
Here are some SIMPLE, PRACTICAL rules of thumb FOR BEGINNERS.
To repeat, this post is FOR BEGINNERS.
The aim here is to allow you to quickly move from the starting line, to being able to confidently use the system in most situations.
Later, you can really learn about the inner workings of these issues.
(1) Don\'t ever say name=@\"hello\"
. Always say self.name=@\"hello\"
. Do a project-wide search for name
and ensure you always say self.name
and not name
, when you set it or change it.
(2) You know all that infuriating stuff about memory management, initialising, releasing and so on. If you use the self thingy, it takes care of all that for you. Cool huh?
(3) The self thingy is particularly useful because you can easily \"change\" the string (or whatever it is) as you go along. So, it\'s totally OK to do this,
self.name=@\"aa\";
self.name=@\"bb\";
self.name=@\"cc\";
whereas (in a word) you can never, ever, for any reason, do this...
name=@\"aa\";
name=@\"bb\";
name=@\"cc\";
( * ) Regarding your literal question, \"please explain the difference between name = @\"hello\"
and self.name = @\"hello\"?\"
This is easy to do.
The first one is just setting a variable. You know, exactly like \"x=42\"
in the old days when life was simple and we were 13 years old.
The second one is completely different, specifically it is calling a complicated routine (known as \"the setter\") to do a whole lot of amazing and astonishing stuff for you.
So that is the literal answer to your question. The first one just sets the variable (and don\'t forget, there are a whole lot of pointers and other weird stuff involved, and as a rule you certainly can not just set pointers willy-nilly like that). The second one actually calls a big complicated routine and hence does a whole lot of stuff for you.
Once again, the second one is exactly like saying...
[name bigComplicatedRoutineHere:@\"hello\"];
...it is very helpful to always remember that the syntax self. ...
is literally calling a routine.
Indeed, some thinkers on the topic thought it was a dumb idea when they introduced this self.X
syntax to mean [X complicatedThingHere]
. It introudces a lot of confusion, and every beginner asks exactly what you are asking.
Personally, it took me over nine years to get this clear in my head. :-) So again, I emphasise that you must remember that when you say self.x
, in fact, you are actually calling a routine.
To repeat: the \"self dot\" syntax in fact calls a routine. (Indeed I believe one of the preprocessors simply expands it to [x amazingStuffHere]
. )
I have tried to answer in a way that will keep you going and allow you to advance and use more features, while you learn about memory management, properties, and so on. If you are more advanced than this post, just ignore it.
Please note that this post is meant to be advice for beginners to enable them to keep going and not get infuriated. Hope it helps!
2014 update! Important Note on ARC for beginners ...
Note, this post is five years old now! It\'s been read by thousands of beginners and there have been many followup questions etc. Please note that, today in the new \"ARC world\". To some extent: if you\'re a beginner: you should pretty much only use!! properties. ie, use \"self.whatever\" at all times, everywhere. In any event, just be aware that the information in this post is \"largely historic\" and is becoming more so every day. Of course, it goes without saying that once you are an expert, you will need to and will understand every subtle detail of all this. Hope it helps someone.
self.name
uses the accessor and/or mutator defined by you (this is nonatomic and retain in your case). So when you call self.name = foo
, it will call the setName:(NSString *)str
mutator generated by the compiler, which will first release the current string, then retains the new string and finally sets name to the retained string.
Just calling name = foo
does nothing more than assigning name to foo.
This also means that you can only call self.xxx
when you have defined a property for the ivar, otherwise the compiler will tell you that it doesn\'t know about it(iVar).
name = @\"Joe\"
You\'re accessing directly the variable, bypassing the getter method that Cocoa took the trouble of creating for you. Usually, not the wisest thing to do.
self.name = @\"Joe\"
Now your going through the method you asked cocoa to create for you. This is usually the best way.
As a rule of thumb, use always the setter and getter provided by Cocoa, with ONE exception: dealloc. In dealloc, you should always release the variable directly, not through the getter method:
-(void) dealloc {
[name release]; // instead of [[self name] release]
...
[super dealloc];
}
The reason to avoid accessors in dealloc is that if there are observers or an override in a subclass that triggers behavior, it\'ll be triggered from dealloc which is pretty much never what you want (because the state of the object will be inconsistent).
OTOH, there\'s also a slightly more convenient syntax for declaring iVars that you might not be aware of. If you are only targeting 64bit macs, You can use properties to generate both accessor methods and the instance variable itself:
#import <Cocoa/Cocoa.h>
@interface Photo : NSObject
@property (retain) NSString* caption;
@property (retain) NSString* photographer;
@end
It\'s real a memory management, firt the property grammar is real setter and getter method, when use self.xxx = ?, it could call setter method, the object retain cout +1, name can not be release, however if name = foo is nothing about property grammar.
setter method example:
-(void)setObj:(ClassX*) value
{
if (obj != value)
{
[obj release];
obj = [value retain];
}
}