I'm still struggling with the syntax errors in @implementation section.
So, I want to understand the difference between using @property and not.
First case is would be one @interface where i declared some variable in {}.
//ViewController.h
#import <UIKit/UIKit.h>
#import "Student.h" // just class i made
@interface ViewController : UIViewController
{
Student *stObj;
}
And, i'm trying to refer to stObj pointer using several identifier ( _(underscore), self. , self->, nothing)
// ViewController.m
#import "ViewController.h"
@interface ViewController () // just leaving this code cuz i haven't study what it is :)
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
stObj = [[Student alloc]init ]; //no error
//self->stObj = [[Student alloc]init]; //no error
//self.stObj = [[Student alloc]init]; //error!
//_stObj = [[Student alloc]init]; //error!
}
Second case is would be one @interface where i use @property
@interface ViewController : UIViewController
@property Student *stObj;
@end
and do the same thing like above.
stObj = [[Student alloc]init ]; //error
//self->stObj = [[Student alloc]init]; //error
//self.stObj = [[Student alloc]init]; //no error!
//_stObj = [[Student alloc]init]; //no error!
SO, as you can see what i had to assume was that self. and _ (underscore) worked and seems similar ...?
The Question is that what @property actually does causing different result..?
Thank you for reading my question and if i'm doing something wrong please correct me.
First, let's explain what a property is: it's basically a set of methods, usually for accessing an instance variable. That's an overly simple (and slightly incorrect) explanation but it will suffice most of the time.
You can define the name of the instance variable with the
@synthesize
keyword, as in:In this case, the compiler will generate:
somethingElse
of typeType
.foo
: it just returns the content of the variablesomethingElse
.setFoo:
: it sets the content of the variablesomethingElse
and takes care of notifying key-value observers.If you don't specify a
@synthesize
statement, the compiler will automatically generate an instance variable with the property name prefixed by an underscore. So if your property is namedfoo
, the automatically created instance variable is called_foo
.When you do:
(without a
@synthesize
) the compiler generates:_stObj
of typeStudent *
.stObj
that reads the content of the variable_stObj
.setStObj:
that writes the content of the variable_stObj
.Next, access to instance variables: you can either access them by their name directly, if the scope allows it (like
_foo
), or you can access them via the->
dereference operator as inself->_foo
. The later also allows you to access public instance variables of other objects, as inotherObject->_foo
. Don't do this unless you really know what you're doing, though.Last but not least, the dot-notation. Writing
obj.method
is the same as writing[obj method]
and writingobj.method = value
is the same as writing[obj setMethod:value]
. That is, the dot-notation is a shorter syntax for a method call. (I tend to avoid it since it's also the notation for access struct members, but that's just me.)With that knowledge, your examples are easy to explain:
In your first example:
In your second example:
@property
automatically implements accessors for the instance variable (and will even create the instance variable if none is specified). So@property Student *stObj;
is the equivalent och defining and implementing-(Student *)stObj;
and-(void)setStObj:(Student*)student;
.The reason that
stdObj = …
fails is that the default variable name is the property named prefixed with an underscore, so_stdObj = …
will work.The difference is that a
@property
is not an instance variable; rather, it is the getter/setter for an instance variable.When used with properties, dot syntax will call the
(void)setObject:(id)object
and(id)object
methods -- the accessor/mutator for the underlying instance variable. By default, the underlying instance variable is the property name prefixed by an underscore -- this is why you typically don't need@synthesize stdObj = _stdObj
because that is the default behavior.With that in mind, if you were to declare a simple iVar,
self.stdObj
would be illegal unless you declared a getter/setter for that iVar (or made it a property).self->stdObj
directly accesses the iVar.